M.B.
M.B.

Reputation: 37

Segmentation Fault when trying to push element into stack from a switch case menu

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

Answers (2)

Stas Simonov
Stas Simonov

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

Eric Postpischil
Eric Postpischil

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:

  • Test the result of scanf to see that it is 1, indicating scanf assigned one item.
  • Test the value scanf stored in the int to see if it is in an acceptable range.

Upvotes: 3

Related Questions