最近在我们的数据结构课程中,我们介绍了堆栈,并承担了在无限循环中使用 switch case 菜单实现堆栈的任务。这应该很容易,但是使用动态内存分配,我在将元素推送到堆栈中时不断遇到此段错误,这是我在 VS Code 调试器的帮助下检测到的。
这是需要注意的代码(我省略了 pop() 和 display(),因为执行永远不会到达那里):
#include<stdio.h>
#include<stdlib.h>
int top = -1 ;
int n ;
int main()
{
void push(int*,int) ;
int pop(int*) ;
void display(int*) ;
printf("Enter no. of elements: ") ;
scanf("%d",&n) ;
int* a = (int*)malloc(n*sizeof(int)) ;
char c ;
while(1)
{
printf("Enter 1. to push.\nEnter 2. to pop.\nEnter 3. to display.\nEnter anything else to exit.\n") ;
scanf("%d",&c) ;
int e ;
switch(c)
{
case 1:
printf("Enter the no. to be pushed: ") ;
scanf("%d",&e) ;
push(a,e) ;
break ;
case 2:
e = pop(a) ;
printf("%d got popped.\n",e) ;
break ;
case 3:
display(a) ;
break ;
default:
exit(1) ;
}
}
free(a) ;
return 0 ;
}
void push(int* a,int e)
{
top++ ;
if(top==n)
{
printf("Stack Overflow.\n") ;
exit(1) ;
}
a[top] = e ;
}
您可能会想:为什么在 switch case 中使用 char 变量?令我惊讶的是,当使用 int 类型作为“c”时,程序按预期运行,直到我意识到使用 char 变量不仅允许用户输入整数,还可以输入任何键来退出程序。 分段错误总是发生在最后一行:
a[top] = e ;
它提出了一个有趣的困境,打败了我。为什么 char 变量会导致段错误?两者是两个完全不相关的东西,而 int 类型却获得了免费通行证?或者是我在一段时间后回到电脑时错过了一些琐碎的事情?
"%d"
告诉 scanf
期待 int
。 scanf("%d",&c)
向其传递 c
的地址,即 char
。
当
scanf
尝试将 int
写入您传递的地址时,它可以覆盖 c
之外的内存。这可能是您的程序用于其他目的的内存,并且可能会导致您的程序以各种方式误入歧途。
大多数编译器都会对此进行诊断。编译时启用警告并升级为错误。对于 Clang,从
-Wmost -Werror
开始。对于 GCC,从 -Wall -Werror
开始。对于 MSVC,从 /W3 /WX
开始。