Reputation: 37
Recently in our data structures course , we have been introduced to the stack and had the task of implementing one with a switch case menu in an infinite loop . This should have been easy but using dynamic memory allocation , I kept running into this segfault while pushing elements in the stack which I detected with the help of the VS Code debugger.
This is the code requiring attention(I have omitted the pop() and display() as the execution never reaches there):
#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 ;
}
You might think : why use a char variable in the switch case ? Well to my surprise , the program ran as expected when used an int type for 'c' until I realized having char variable would allow the user to input not just an integer but any key to exit out of the program .
The segmentation fault always occurs right on the last line :
a[top] = e ;
It brought up an interesting dilemma which defeated me . Why should the char variable be causing a segfault ? Both are two completely unrelated things and the int type gets the free pass though? Or is it that I am missing something trivial coming back to the computer after quite some time ?
Upvotes: 0
Views: 67
Reputation: 582
sizeof(char)
is 1, but sizeof(int)
is 4 (supposedly). So the scanf
function according to its format string "%d"
writes the excessive int
bytes into an unwanted locations. The memory corruption usually leads to the "Segmentation fault".
Upvotes: 2
Reputation: 222486
"%d"
tells scanf
to expect an int
. scanf("%d",&c)
passes it the address of c
, a char
.
When scanf
attempts to write an int
to the address you passed, it can overwrite memory outside of c
. That may be memory your program is using for some other purpose, and that can cause your program to go astray in various ways.
Most compilers would diagnose this. Compile with warnings enabled and elevated to errors. With Clang, start with -Wmost -Werror
. With GCC, start with -Wall -Werror
. With MSVC, start with /W3 /WX
.
Trying to limit the value scanf
assigns to your variable to char
values is not an appropriate method of validating user input or protecting your program from consequences. For elementary learning purposes, you can start with these two steps:
scanf
to see that it is 1, indicating scanf
assigned one item.scanf
stored in the int
to see if it is in an acceptable range.Upvotes: 3