0

I'm new to C and I'm trying to write a program with a lot of user input. For that purpose I wrote this function:

char * addValue(char * msg){
    char * input[80];
    printf("%s", msg);
    fflush(stdout);
    fgets(*input, 80, stdin);
    strtok(*input, "\n");
    return *input;
}

This function works perfectly in the whole program except in this part:

struct User{
    char userid[10];
    char email[80];
    char name[80];
    char password[80];
    char downloaded[10];
    char registred[10];
};

int change() {
    char * query = "SELECT * FROM Users WHERE user_id=";
    char * userid = addValue("Enter the User ID: "); // Works here
    // Here is a MySQL query
    char * email = addValue("Mail: "); // -> Segmentation Fault
    printf("%s\n", email);
    struct User usrvalues;
    strcpy(usrvalues.email, email);
    return 0;
}

I have absolutely no idea, why the second function call is not working. I have other functions in the program where I call the addValue() function multiple times without any errors.

When I debug this with gdb, I get this result:

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff6445b77 in __GI__IO_getline_info () from /usr/lib/libc.so.6

bt gives me the following informations:

#0  0x00007ffff6445b77 in __GI__IO_getline_info () from /usr/lib/libc.so.6
#1  0x00007ffff6444a3d in fgets () from /usr/lib/libc.so.6
#2  0x000000000040142b in addValue ()
#3  0x00000000004016e9 in change ()
#4  0x0000000000401bd0 in main ()

I tried different inputs ("" (an empty string), different numbers like 100 and different strings like "test"), but it every time it ends with a segmentation fault.

What am I doing wrong?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Marcel Kapfer
  • 573
  • 4
  • 13
  • 1
    You have `char *input[80];` which is an array of 80 uninitialized pointers. You probably want `char input[80];`, though I'm not convinced the line limit should be that short (you can only read 78-character lines, plus a newline, plus a null into it). I tend to use numbers like 4096, partly for the shock value. You could use 256 sanely. You'll then need to fix the call to `fgets()` and `strtok()`. You also have to decide how you'll handle returning the data to the calling function; you can't simply return a pointer to a local array (it doesn't exist after the function returns). – Jonathan Leffler Jul 09 '15 at 15:53

1 Answers1

3

input is an uninitialized array of pointers. By doing *input you get the first uninitialized pointer and pass it to fgets.

I'm sure you didn't mean to create an array of pointers to char, but an array of char:

char input[80];

However, you have a more serious problem than that, because you then return a pointer to this local array input (well, after the change described above you would), and that leads to undefined behavior because local variables are local, they disappear when the function returns and will leave you with a stray pointer.

You have two solutions to this problem: The first is to declare the array in the calling function, and pass it (and its size) to the function, just like you pass input and its length to fgets now.

The second solution is to create the array dynamically using malloc, and then remember to free it once you're done with it.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621