Search code examples
cnetwork-programminguser-inputstdinposix-select

Segmentation fault when reading the user input from STDIN


I am trying to read the user input from the file descriptor '0' (STDIN) using the following program. Before, it had no problem, but after a few changes in other parts of the program it gives me a segmentation error while reading the input. I also removed the "FD_CLR(0, &readfds)" to see if it works, but it doesn't. Could you please check where the problem is?

        char *userInput;
        FD_ZERO(&masterfds);
        FD_SET(0, &masterfds);
        FD_SET(udp_con, &masterfds);
        maxfds = udp_con;

        while(exit == false)
        {               
            readfds = masterfds;

            selectFunc = select(maxfds+1, &readfds, NULL, NULL, &tv);
            if(selectFunc < 0)
            {
                message("error in select");
                exit = true;
            }
            else if(selectFunc == 0) //If there is a timeout
            {

            }
            else //If a file descriptor is activated
            {
                if(FD_ISSET(udp_con, &readfds)) //If there is an activity on udp_con
                {
                    /*read the udp_con via recvfrom function */
                } 
                if(FD_ISSET(0, &readfds)) //If There is an input from keyboard
                {

                    /* When it reaches to this part, the program shows a "segmentation fault" error */
                    fgets(userInput, sizeof(userInput), stdin);
                    int len = strlen(userInput) - 1;
                    if (userInput[len] == '\n')
                    {
                        userInput[len] = '\0';
                    }
                    string str = userInput;
                    cout<<"The user said: "<<str<<endl;                         
                    commandDetector(str);
                    FD_CLR(0, &readfds);
                }                   
            }
        }

Solution

  • You're declaring userInput as a char *. This gives you a pointer pointing to some random location which you almost certainly don't own and can't write to. If this ever worked it's down to pure (bad) luck.

    The easiest way to fix this is to declare userInput as an array, something like:

    char userInput[1024];.

    This will make userInput an array of 1024 chars which you can modify as much as you want, and specifically can pass into fgets for it to write to.

    Another way is to use malloc to get some memory:

    char *userinput = malloc(1024);
    

    If you do this you will also have to change your call to fgets because sizeof(userInput) will yield the size of the pointer (typically 4 or 8) rather than the size of the memory it points to. So something like:

    fgets(userInput, 1024, stdin);
    

    Also if you get memory from malloc you should call free when you're done with it, so:

    free(userInput);