Thread: segmentation fault (if input == var) program compiles

  1. #1
    Registered User
    Join Date
    Feb 2018
    Location
    San Diego, CA
    Posts
    123

    Cool segmentation fault (if input == var) program compiles

    Hey all, this exercise is out of "Beginning C 5th Edition" and it's much easier than working through the Project Euler problems but I am still working on them too. Here is the exercise question:

    "The logic of the program is quite straightforward. The program must generate a sequence of integers between 0 and 9 and display the sequence on the screen for one second before erasing it. The program should then read the player’s pathetic attempt to enter the identical sequence of digits. If the player is lucky enough to get the sequence correct, the computer should repeat with another sequence of the same length. If the player’s luck holds out for three successive sequences of a given length, the program should continue by displaying a longer sequence for the player to try. This continues until the player’s luck runs out and he or she gets a sequence wrong. The program will then calculate a score based on the number of successful tries and the time taken and invite the player to play again."

    Please, I am getting Segmentaton Fault but program runs fine but cannot get a successful entry to see if there was a match for the scanf entry. This if() statement:

    Code:
            if (input == num)
    again, this exercise was much easier than the project euler problems but it is preparing me for them (this exercise came out of a chapter on Loops and it's good to freshen up on the nested for loops for the project euler problems) and I haven't even touched K&R yet.

    Code:
    /* Chapter 4 Exercise from C Programming book 2/14/2020 */
    
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <ctype.h>
    
    
    void delay (int seconds)     // delay function i got this source code from google
    {
        unsigned long int count=333333333, i, j;
    
    
        for(i = 0;i<seconds;i++)
            for(j = 0; j < count; j++);
    }
    
    
    int main (void)
    {
    
    
        int limit = 9;
        int count, num = 0;
        char c = 'X';
        int i;
        int input = 0;
        char newgame;
        time_t t;
        srand((unsigned) time(&t));
    
    
        // output text %d\t
        for (;;)         // game loop
        {
            printf("\n");
    
    
            for (count = 1; count <= 9; count++)      // generate random number loop digit from 0 -> 9
            {
                num = rand() % limit;
                printf("%d", num);
            }
    
    
    
    
            printf("\n");
    
    
            delay(1);     // create 1 second program delay before clear screen with 'X's
    
    
            // clear screen with x's
            for (int ctr_1 = 1; ctr_1 < 7500; ctr_1++)
            {
                printf("%c", c);
            }
    
    
            printf("\n\n");
    
    
            printf("What sequence was inserted?: ");
            scanf("%d", input);
    
    
            if (input == num)  // corrected answer was inserted
            {
                // go back to beginning of program for 3 times
                /*
                for (i = 1; i < 3; i++) // loop for correct answer for 3 times & increase sequence length if true three times
                {
                    ;
                }
                */
                printf("Correct answer!\n");
            }
    
    
            else  // answer was incorrect
            {
                // new games? Yes or no (tolower)
                /*
                printf("Do you want a new game? (Y or N)\n");
                scanf("%c", newgame);
    
    
                if(tolower(newgame) == 'n') // look for any sign of no (not case sensitive)
                {
                    return 0;
                    //exit(1);     // do this...
                }
    
    
                else     // 'y' was inserted
                {
                    // start new game
                }
                */
                printf("\nError!\n");
            }
        }
    
    
        return 0;
    }
    Last edited by _jamie; 02-14-2020 at 11:49 PM. Reason: fixed typo

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Seriously, compile with warnings and fix them before running code.
    Code:
    $ gcc -Wall foo.c
    foo.c: In function ‘main’:
    foo.c:63:15: warning: format ‘%d’ expects argument of type ‘int *’, but argument 2 has type ‘int’ [-Wformat=]
             scanf("%d", input);
                   ^
    foo.c:26:10: warning: unused variable ‘newgame’ [-Wunused-variable]
         char newgame;
              ^
    foo.c:24:9: warning: unused variable ‘i’ [-Wunused-variable]
         int i;
             ^
    $
    > if (input == num)
    No, it's the completely borked scanf attempt which fails to pass a pointer which generates the actual fault.

    And even if you get no warnings, you do this.
    Run the code in the debugger, and it will tell you exactly the line where the problem originated.
    Code:
    $ gcc -g -Wall foo.c
    $ gdb -q ./a.out 
    Reading symbols from ./a.out...done.
    (gdb) run
    <<snipped>>
    What sequence was inserted?: 333333
    
    Program received signal SIGSEGV, Segmentation fault.
    0x00007ffff7a6cde5 in _IO_vfscanf_internal (s=<optimised out>, format=<optimised out>, argptr=argptr@entry=0x7fffffffdd58, errp=errp@entry=0x0) at vfscanf.c:1902
    1902	vfscanf.c: No such file or directory.
    (gdb) bt
    #0  0x00007ffff7a6cde5 in _IO_vfscanf_internal (s=<optimised out>, format=<optimised out>, argptr=argptr@entry=0x7fffffffdd58, errp=errp@entry=0x0) at vfscanf.c:1902
    #1  0x00007ffff7a785df in __isoc99_scanf (format=<optimised out>) at isoc99_scanf.c:37
    #2  0x000000000040081d in main () at foo.c:63
    (gdb) frame 2
    #2  0x000000000040081d in main () at foo.c:63
    63	        scanf("%d", input);
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Feb 2018
    Location
    San Diego, CA
    Posts
    123

    Exclamation

    I ran the code through gdb couldn't make sense out of it, complained about line 13 though and kept showing random numbers
    Quote Originally Posted by Salem View Post
    Seriously, compile with warnings and fix them before running code.
    Code:
    $ gcc -Wall foo.c
    foo.c: In function ‘main’:
    foo.c:63:15: warning: format ‘%d’ expects argument of type ‘int *’, but argument 2 has type ‘int’ [-Wformat=]
             scanf("%d", input);
                   ^
    foo.c:26:10: warning: unused variable ‘newgame’ [-Wunused-variable]
         char newgame;
              ^
    foo.c:24:9: warning: unused variable ‘i’ [-Wunused-variable]
         int i;
             ^
    $
    > if (input == num)
    No, it's the completely borked scanf attempt which fails to pass a pointer which generates the actual fault.

    And even if you get no warnings, you do this.
    Run the code in the debugger, and it will tell you exactly the line where the problem originated.
    Code:
    $ gcc -g -Wall foo.c
    $ gdb -q ./a.out 
    Reading symbols from ./a.out...done.
    (gdb) run
    <<snipped>>
    What sequence was inserted?: 333333
    
    Program received signal SIGSEGV, Segmentation fault.
    0x00007ffff7a6cde5 in _IO_vfscanf_internal (s=<optimised out>, format=<optimised out>, argptr=argptr@entry=0x7fffffffdd58, errp=errp@entry=0x0) at vfscanf.c:1902
    1902    vfscanf.c: No such file or directory.
    (gdb) bt
    #0  0x00007ffff7a6cde5 in _IO_vfscanf_internal (s=<optimised out>, format=<optimised out>, argptr=argptr@entry=0x7fffffffdd58, errp=errp@entry=0x0) at vfscanf.c:1902
    #1  0x00007ffff7a785df in __isoc99_scanf (format=<optimised out>) at isoc99_scanf.c:37
    #2  0x000000000040081d in main () at foo.c:63
    (gdb) frame 2
    #2  0x000000000040081d in main () at foo.c:63
    63            scanf("%d", input);
    Thanks Salem for the post. Look at this code (this program finds a succesful match for '10' inserted

    Code:
    #include <stdio.h>
    
    
    int main()
    {
        int a = 10;
        int b;
    
    
        printf("Insert number: ");
        scanf("%d", &b);
    
    
        if(b == a)
        {
            printf("correct answer\n");
        }
    
    
        else
        {
            printf("Error, no match\n");
        }
    
    
        return 0;
    }
    Here's my code again that Salem commented on, with a few commented out additions. I'm not getting correct program output for if (input == num). Also, Salem, I reviewed your comment about running cc (gcc) with -Wall switch (I am on Debian Linux) and I believe it is now time to use gdb I have been using C + vim + cc for 2 years Thanks for finding the above typo, the missing '&' on the &input for scanf() function. Please, what am I missing in comparing my code to these two programs?

    Code below, similar if statement functions, program not finding match (always returning "else" function)

    Code:
    /* Chapter 4 Exercise from C Programming book 2/14/2020 */
    
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <ctype.h>
    
    
    void delay (int seconds)     // delay function i got this source code from google
    {
        unsigned long int count=333333333, i, j;
    
    
        for(i = 0;i<seconds;i++)
            for(j = 0; j < count; j++);
    }
    
    
    int main (void)
    {
    
    
        int program_execution = 0;
        int game_loop = 0;
        int limit = 9;  // max digits to generate for random number
        int count, num = 0;
        char c = ' ';  // fill console with blank space to clear screen
        int input;
        time_t t;
        char newgame;
        int successful_tries = 0;
        srand((unsigned) time(&t));
    
    
        for(;;)
        //for ( ; game_loop > 0; --game_loop) // count down how many tries left until program ends
        {
            printf("\n");
    
    
            for (count = 1; count <= 9; count++)      // generate random number loop digit from 0 -> 9
            {
                num = rand() % limit;
                printf("%d", num);
            }
    
    
            printf("\n");
    
    
            delay(1);     // create 1 second program delay before clear screen with 'X's
    
    
            // clear screen with x's
            for (int ctr_1 = 1; ctr_1 < 7500; ctr_1++)
            {
                printf("%c", c);
            }
    
    
            printf("\n\n");
    
    
            printf("What sequence was inserted?: ");
            scanf(" %d", &input);
    
    
            if (input == num)  // corrected answer was inserted, increase sequence length. Go to beginning of progrem (program_begin--), sequence_length++);
            {
                printf("Correct Answer!\n");
                /*
                while (input == num)
                {
                    printf("Error! Answer was Incorrect!\n");
                    printf("Do you want a New Game? (Y or N)\n");
                    scanf("%c", &newgame);
                    if(tolower(newgame) == 'y') // look for any sign of no (not case sensitive)
                    {
                        break;
                    }
    
    
                    else
                    {
                        printf("Error!\n");
                    }
                }
                */
            }
    
    
            else
            {
                //++successful_tries;
                printf("Error, Not Correct!\n");
            }
        }
    }
    
    
                // The program will the calculate a score based on the number of successful tries and the time taken and invite the player to play again.
    
    
        //printf("You had %d successful try. Program execution took %d seconds.\n", successful_tries, program_execution);
    Last edited by _jamie; 02-16-2020 at 04:15 PM. Reason: forgot to include second code

  4. #4
    Registered User
    Join Date
    Feb 2018
    Location
    San Diego, CA
    Posts
    123
    Hey all, i believe the scanf() function is getting confused with a for loop or the delay() function resulting in a confused scanf() function, resulting in there being no exact match for the if (input==num) function, therefor it always goes to else, even when an exact 9 sequence match is typed in. I was wondering if something like this would help, as i've used this before on another program, but someone later said it wasn't completely 100% correct.

    Code:
    while((getchar()) != '\n');

  5. #5
    misoturbutc Hodor's Avatar
    Join Date
    Nov 2013
    Posts
    1,787
    Code:
            for (count = 1; count <= 9; count++)      // generate random number loop digit from 0 -> 9
            {
                num = rand() % limit;
                printf("%d", num);
            }
    The code above is only storing one random number (digit) between 0 and 9. E.g. if this produces the sequence 1 2 3 4 5 6 7 8 9 then the user has to enter 9 for the input == num condition to be true.

    As for the delay function... I doubt that's doing anything at all and if you turn on optimisation (e.g. compile with, say, -O2 using gcc) then the compiler will optimise the loops away as dead code

  6. #6
    Registered User
    Join Date
    Feb 2018
    Location
    San Diego, CA
    Posts
    123
    Thanks for the followup Hodor, I misread the Exercise question. Looks like the book wasn't asking for a 9 digit number, that would be beyond my capabities and isn't mentioned in the Chapter, also I have removed the for loop and added this:

    Code:
    srand(time(NULL));
    num = 1 + rand() % limit;
    this now makes the code easier to work with



    Quote Originally Posted by Hodor View Post
    Code:
            for (count = 1; count <= 9; count++)      // generate random number loop digit from 0 -> 9
            {
                num = rand() % limit;
                printf("%d", num);
            }
    The code above is only storing one random number (digit) between 0 and 9. E.g. if this produces the sequence 1 2 3 4 5 6 7 8 9 then the user has to enter 9 for the input == num condition to be true.

    As for the delay function... I doubt that's doing anything at all and if you turn on optimisation (e.g. compile with, say, -O2 using gcc) then the compiler will optimise the loops away as dead code
    Last edited by _jamie; 02-16-2020 at 11:01 PM. Reason: fixed typo

  7. #7
    Registered User
    Join Date
    Feb 2018
    Location
    San Diego, CA
    Posts
    123
    This is what I came up with...there are a few bugs, and i'll work on it more tomorrow. Any suggestions running it through gdb? That's my next step, using gdb.

    Code:
    /* Chapter 4 Exercise from C Programming book 2/14/2020 */
    
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <ctype.h>
    
    
    void delay (int seconds) 	// delay function i got this source code from google
    {
    	unsigned long int count=333333333, i, j;
    
    
    	for(i = 0;i<seconds;i++)
    		for(j = 0; j < count; j++);
    }
    
    
    int main (void)
    {
    
    
    	int game_loop = 3;
    	char c = ' ';  // fill console with blank space to clear screen
    	int successful_tries = 0;
    	char newgame = 0;
    	int num = 0;
    	int input = 0;
    	int limit = 9;
    	int limit_2 = 1;
    
    
    	printf("This is a game to test your memory, with a random number of 1 digit that will be displayed a max of 3 successive times.\n");
    	clock_t t;
    	t = clock();
    	//for (;;)
    	for ( ; game_loop > 0; --game_loop) // count down how many tries left until program ends
    	{
    		// code to compute random digits
    		srand(time(NULL));
    		num = limit_2 + rand() % limit;
    	
    		printf("\n");
    
    
    		printf("%d", num);
    
    
    		delay(1); 	// create 1 second program delay before clear screen with 'X's
    
    
    		// clear screen with x's
    		for (int ctr_1 = 1; ctr_1 < 7500; ctr_1++)
    		{
    			printf("%c", c);
    		}
    
    
    		printf("\n\n");
    
    
    		printf("\nYou have %d tr%s left.\n", game_loop, game_loop == 1 ? "y" : "ies");
    		printf("What sequence was displayed?: ");
    		scanf("%d", &input);
    
    
    		if (input == num) // corrected answer was inserted, increase sequence length. Go to beginning of progrem (program_begin--), sequence_length++);
    		{
    			printf("Correct Answer!\n");
    			
    			int i = 0;
    
    
    			// where's score variable
    
    
    			while (i < 1)  // per one match (one correct match)
    			{
    				successful_tries += 1; // Successful tries for end of program
    				++i;
    			}
    
    
    			if (successful_tries == 3) // sequence was inserted 3 times in a row
    			{
    				limit += 191; // make sequence 3 digits
    				limit_2 += 49;  // limit_2 = limit_2 + 49;
    			}
    
    
    			if (successful_tries >= 3) // if successful_tries is greater than or equal to 3
    			{
    				game_loop += 1; // increment game_loop + 1 infinitely
    			}
    		}
    
    
    		else if (input != num)
    		{
    			printf("Error! Answer was Incorrect!\n");
    			printf("Do you want a New Game? ('n' to Exit)\n");
    			scanf("%c", &newgame);
    			while ((getchar()) != '\n');
    			if(newgame == 'n')
    			{
    				exit(1);
    			}
    
    
    			else if (newgame == 'y')
    			{
    				break;
    				//return; // ERROR (should return to main loop)
    			}
    		}
    	}
    	
    	// The program will then calculate a score based on the number of successful tries and the time taken and invite the player to play again.
    	t = clock() - t;
    	double program_execution = ((double)t)/CLOCKS_PER_SEC; // in seconds
    	printf("You had %d successful tr%s. Program execution took %f seconds.\n", successful_tries, successful_tries == 1 ? "y" : "ies", program_execution);
    
    
    
    
    	return 0;
    }

  8. #8
    Registered User
    Join Date
    Feb 2018
    Location
    San Diego, CA
    Posts
    123
    Please help, wouldn't mind a few suggestions, I know I could just sit here and play with the loops, the whole chapter is on loops (Chapter 4), but I was thinking, is this correct:

    Code:
    		else if (input != num)
    		{
    			printf("Error! Answer was Incorrect!\n");
    			printf("Do you want a New Game? ('n' to Exit)\n");
    			scanf("%c", &newgame);
    			while ((getchar()) != '\n');
    			if(newgame == 'n')
    			{
    				exit(1);
    			}
    
    
    			else if (newgame == 'y')
    My book mentions using "break" to break out of the loop (code mentioned above is two nested else if statements), inserting a 'y' for the else if statement isn't working in the program unless successive_tries is >= 3

    Is this correct, an if() statement, or would a while loop work? How about while (input != num) ?
    Code:
    if (input == num)
    should be a while loop

  9. #9
    Registered User
    Join Date
    Feb 2018
    Location
    San Diego, CA
    Posts
    123
    This code works, this just about finishes the first part of the exercise. I removed the if() and else if() statements inside the else if () statement under the matching (input != num) which was causing the 'break' keyword to not work. A pretty basic exercise. Look forward to working through the rest of it
    Code:
    /* Chapter 4 Exercise from C Programming book 2/14/2020 */
    
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <ctype.h>
    
    
    void delay (int seconds) 	// delay function i got this source code from google
    {
    	unsigned long int count=333333333, i, j;
    
    
    	for(i = 0;i<seconds;i++)
    		for(j = 0; j < count; j++);
    }
    
    
    int main (void)
    {
    	int game_loop = 3;
    	char c = ' ';  // fill console with blank space to clear screen
    	int successful_tries = 0;
    	//char newgame = 0;
    	int num = 0;
    	int input = 0;
    	int limit = 9;
    	int limit_2 = 1;
    
    
    	printf("This is a game to test your memory, with a random number of 1 digit that will be displayed a max of 3 successive times.\n");
    	clock_t t;
    	t = clock();
    	for ( ; game_loop > 0; --game_loop) // count down how many tries left until program ends
    	{
    		// code to compute random digits
    		srand(time(NULL));
    		num = limit_2 + rand() % limit;
    
    
    		printf("\n%d\n", num);
    		delay(1); 	// create 1 second program delay before clear screen with 'X's
    
    
    		// clear screen with x's
    		for (int ctr_1 = 1; ctr_1 < 7500; ctr_1++)
    		{
    			printf("%c", c);
    		}
    
    
    		printf("\n\n");
    
    
    		printf("\nYou have %d tr%s left.\n", game_loop, game_loop == 1 ? "y" : "ies");
    		printf("What sequence was displayed?: ");
    		scanf("%d", &input);
    
    
    		if (input == num) // corrected answer was inserted, increase sequence length. Go to beginning of progrem (program_begin--), sequence_length++);
    		{
    			printf("Correct Answer!\n");
    			
    			int i = 0;
    
    
    			// where's score variable
    
    
    			while (i < 1)  // per one match (one correct match)
    			{
    				successful_tries += 1; // Successful tries for end of program
    				++i;
    			}
    
    
    			if (successful_tries == 3) // sequence was inserted 3 times in a row
    			{
    				limit += 191; // make sequence 3 digits
    				limit_2 += 49;  // limit_2 = limit_2 + 49;
    			}
    
    
    			if (successful_tries >= 3)
    			{
    				game_loop += 1;
    			}
    
    
    			/*
    			if (successful_tries >= 3) // if successful_tries is greater than or equal to 3
    			{
    				game_loop += 1; // increment game_loop + 1 infinitely
    			}
    			*/
    
    
    		}
    
    
    		else if (input != num) // only quits successful if game_loop is < 3
    		{
    			printf("Error! Answer was Incorrect!\n");
    			//while ((getchar()) != '\n');
    			break;
    		}
    	}
    	
    	// The program will then calculate a score based on the number of successful tries and the time taken and invite the player to play again.
    	t = clock() - t;
    	double program_execution = ((double)t)/CLOCKS_PER_SEC; // in seconds
    	printf("You had %d successful tr%s. Program execution took %f seconds.\n", successful_tries, successful_tries == 1 ? "y" : "ies", program_execution);
    
    
    
    
    	return 0;
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 6
    Last Post: 12-24-2015, 01:42 PM
  2. Segmentation fault in C++ program
    By jkepler in forum C++ Programming
    Replies: 2
    Last Post: 08-29-2015, 03:41 PM
  3. Segmentation fault in my program
    By Dr.JacKaL in forum C Programming
    Replies: 4
    Last Post: 10-29-2014, 02:31 PM
  4. Segmentation fault on my program
    By blackswan in forum C Programming
    Replies: 2
    Last Post: 05-11-2005, 04:47 PM
  5. Segmentation fault with input test file
    By bentles in forum C Programming
    Replies: 20
    Last Post: 04-28-2002, 08:58 PM

Tags for this Thread