以下代码在第二次Pop()
调用时崩溃。我是C的新手,我现在一直盯着这段代码超过一个小时,我看不出错误。有什么想法可以帮助我解决这个代码崩溃的原因吗?
#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;
}
答案 0 :(得分:11)
在第二个Pop上,堆栈为空,如果堆栈为空,Pop返回NULL。
所以在第二行:
printf("%d\n", *(int*)Pop(intstack));
您正在取消引用NULL
作为指向int
的指针。
printf("%d\n", *(int*)NULL );
答案 1 :(得分:6)
第二个pop尝试从空堆栈弹出,Pop()
函数返回NULL
。然后main函数尝试取消引用这个NULL
- 指针并打印它指向的值。
由于NULL指针未指向任何有效的内容,因此会出现分段错误。
答案 2 :(得分:3)
对Pop
的第二次调用会返回NULL
,然后您将其转换为int *
并尝试取消引用。取消引用NULL
会导致段错误。
答案 3 :(得分:2)
要回显所有以前的答案,问题是对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}};
这种方式0
不会成为特例。
答案 4 :(得分:1)
你试图取消引用你在空案例中返回的NULL。
答案 5 :(得分:0)
“索引”成员是签名还是未签名?如果它是无符号的,则表达式“s-&gt; index--”将导致非常大的数字。
答案 6 :(得分:0)
当我查看你的代码时,我发现另一个也会导致崩溃的问题:我认为你Push()
上也有一个“一个一个”错误,在这里:
void Push(Stack *s, void *v)
{
if(s->index < StackDataSize)
{
s->data[++s->index] = v;
}
...
检查s->index < StackDataSize
,然后执行预增量++s->index
并写入s->data
将在数组末尾写一个s->index == StackDataSize - 1
。这也会给你一个分段错误。