从堆栈中检索项时C程序崩溃
以下代码在第二次调用时崩溃。我是C语言的新手,我已经盯着这段代码看了一个多小时了,我看不到错误。有什么办法可以帮我解释为什么这个代码会崩溃吗从堆栈中检索项时C程序崩溃,c,pointers,stack,C,Pointers,Stack,以下代码在第二次调用时崩溃。我是C语言的新手,我已经盯着这段代码看了一个多小时了,我看不到错误。有什么办法可以帮我解释为什么这个代码会崩溃吗 #include <stdio.h> #define StackDataSize 100 typedef struct Stack { int index; void *data[StackDataSize]; } Stack; void* Pop(Stack *s) { if(s->index >=
#include <stdio.h>
#define StackDataSize 100
typedef struct Stack
{
int index;
void *data[StackDataSize];
} Stack;
void* Pop(Stack *s)
{
if(s->index >= 0)
{
return s->data[s->index--];
}
else
{
fprintf(stderr, "ERROR: Stack Empty\n");
return NULL;
}
}
void Push(Stack *s, void *v)
{
if(s->index < StackDataSize)
{
s->data[++s->index] = v;
}
else
{
fprintf(stderr, "ERROR: Stack Full\n");
}
}
int main(void)
{
Stack s = {-1}, *intstack = &s;
int x = 123456;
Push(intstack, &x);
printf("%d\n", *(int*)Pop(intstack));
printf("%d\n", *(int*)Pop(intstack));
return 0;
}
#包括
#定义StackDataSize 100
typedef结构堆栈
{
整数指数;
void*数据[StackDataSize];
}堆叠;
void*Pop(堆栈*s)
{
如果(s->index>=0)
{
返回s->数据[s->索引--];
}
其他的
{
fprintf(stderr,“错误:堆栈为空\n”);
返回NULL;
}
}
无效推送(堆栈*s,无效*v)
{
如果(s->index数据[++s->索引]=v;
}
其他的
{
fprintf(stderr,“错误:堆栈已满\n”);
}
}
内部主(空)
{
堆栈s={-1},*intstack=&s;
int x=123456;
推送(intstack和x);
printf(“%d\n”,*(int*)Pop(intstack));
printf(“%d\n”,*(int*)Pop(intstack));
返回0;
}
索引成员是否已签名?如果它是无符号的,那么表达式“s->index--”将产生一个非常大的数字。您正在尝试取消对空大小写中返回的NULL的引用。第二个pop尝试从空堆栈中弹出,而pop()
函数返回NULL
。然后,主函数尝试取消引用此NULL
-指针,并打印它所指向的值
由于NULL指针不指向任何有效的对象,因此会出现分段错误。在第二次弹出时,堆栈为空,如果堆栈为空,则Pop返回NULL 所以在第二行:
printf("%d\n", *(int*)Pop(intstack));
您正在将NULL
作为指向int
的指针取消引用
printf("%d\n", *(int*)NULL );
对
Pop
的第二次调用返回NULL
,然后将其转换为int*
,并尝试取消引用。取消引用NULL
会导致segfault。要回显前面的所有答案,问题是对Pop的第二次调用返回NULL,您在对printf()的第二次调用中尝试取消引用
纯粹作为参考,对于基于阵列的堆栈,如果从上到下增长,而不是从下到上增长,则会更容易一些:
void Push(Stack *s, void *v)
{
if (s->index)
s->data[--s->index] = v;
else
// overflow
}
void *Pop(Stack *s)
{
if (s->index < StackDataSize)
return s->data[s->index++];
else
{
// underflow
return NULL;
}
}
...
Stack s = {StackDataSize, {NULL}};
void推送(堆栈*s,void*v)
{
如果(s->索引)
s->data[--s->index]=v;
其他的
//溢出
}
void*Pop(堆栈*s)
{
如果(s->indexdata[s->index++];
其他的
{
//底流
返回NULL;
}
}
...
堆栈s={StackDataSize,{NULL}};
这样
0
就不会成为特例 当我查看您的代码时,我发现另一个问题也会导致崩溃:我认为您在Push()
上也出现了一个“off by one”错误,如下所示:
void Push(Stack *s, void *v)
{
if(s->index < StackDataSize)
{
s->data[++s->index] = v;
}
...
void推送(堆栈*s,void*v)
{
如果(s->index数据[++s->索引]=v;
}
...
检查
s->index
,然后做一个预增量++s->index
并写入s->data
,如果s->index==StackDataSize-1
,则会写入一个数组末尾。这也会导致分段错误。您在调试器中检查过它了吗?停在每行并检查s和索引为空。我想你会同意的,通过检查,它已经签名了。