对于我用C实现的堆栈,我在推送元素方面存在一些问题。
栈已使用init_size的大小进行了初始化,但是当指针顶部到达栈顶时,当新元素将被推入栈时,我会增加栈的大小。
但是,如果我将struct sqStack sq的引用传递给push函数,则代码可以正常工作;如果我传递sqStack指针* st,则代码在“ * sq-> top ++ = e;”行被错误压缩。在push函数中,如下面的代码所示(尽管有时效果很好)。
对于pop函数,我没有释放所有弹出的元素,可以吗?
谁能帮我找出问题所在?谢谢!
#include <stdio.h>
#include <stdlib.h>
#define init_size 10
#define increment 1
typedef struct sqStack
{
int* top;
int* base;
int stack_size;
}sqStack;
int init_stack(sqStack* sq)
{
if(sq->base==NULL)
{
sq->base = (int*)malloc(init_size*sizeof(int));
}
if(sq->base==NULL) exit(-1);
sq->stack_size=init_size;
sq->top=sq->base;
return 1;
}
int push(sqStack* sq, int e)
{
if(sq==NULL) exit(-1);
if(sq->top-sq->base==sq->stack_size-1)//pointer top reaches the top of the stack
{
int* q = (int*)realloc(sq->base,(init_size+increment)*sizeof(int));
if(q==NULL) exit(-1);
sq->base=q;
sq->top=sq->base+sq->stack_size-1;
sq->stack_size += increment;
}
*sq->top++=e;//Thread 1: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
return 1;
}
int pop(sqStack* sq,int* e)
{
if(sq==NULL) exit(-1);
if(sq->base==sq->top) exit(-1);
sq->top--;
*e=*sq->top;
return *e;
}
int empty(sqStack* sq)
{
if(sq->base==sq->top) return 1;
else return 0;
}
int main() {
/*sqStack sq ;
init_stack(&sq);
int a;
for(int i=0;i<12;i++)
{
push(&sq,i+1);
}
for(int i=0;i<12;i++)
{
printf("%d\n",pop(&sq,&a));
}*/
sqStack* st= (sqStack*)malloc(sizeof(sqStack)) ;
int e;
init_stack(st);
for(int i=0;i<12;i++)
{
push(st,i+1);
}
for(int i=0;i<12;i++)
{
printf("%d\n",pop(st,&e));
}
return 0;
}
如果要测试参考部分,只需取消注释main中代码的第一部分,而main中第二部分是指针部分。
答案 0 :(得分:1)
malloc
函数不会初始化它分配的内存,它将具有不确定(看似随机)的内容。
这意味着if (sq->base==NULL)
函数中的条件init_stack
可能为 false ,当您开始取消引用该指针时会导致undefined behavior。
在init_stack
函数中将所有成员都视为“垃圾”,并无条件分配内存。或在调用init_stack
之前初始化成员(例如,改为使用calloc
。
push
函数中还有一个逻辑错误,在此函数中,您使用init_size+increment
在realloc
调用中计算新的大小。问题在于init_size
和increment
都不会改变,因此,每次调用realloc
时,它们的大小将完全相同。
这当然意味着,当您更改sq->stack_size
时,从第二次致电realloc
起就是错误的。这又导致未定义的行为,因为这样您就有可能超出分配的内存范围。
计算新的大小时,请使用堆栈的当前大小,例如sq->stack_size + increment
。