2015-07-09 3 views
0

Я новичок в C, и я пытаюсь написать программу с большим количеством пользовательских вводных данных. Для этой цели я написал эту функцию:C: Ошибка сегментации при чтении пользовательского ввода с помощью fgets

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

Эта функция отлично работает во всей программе, кроме этой части:

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; 
} 

Я не имею ни малейшего понятия, почему вызов второй функции не работает. У меня есть другие функции в программе, где я вызываю функцию addValue() несколько раз без ошибок.

Когда я отладка это с помощью GDB, я получаю этот результат:

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

bt дает мне следующую информацию:

#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() 

Я пробовал различные входы ("" (пустую строку), разные числа, такие как 100 и разные строки, такие как «тест»), но каждый раз, когда он заканчивается ошибкой сегментации.

Что я делаю неправильно?

+1

У вас есть 'char * input [80];' который представляет собой массив из 80 неинициализированных указателей. Вероятно, вам нужен 'char input [80];', хотя я не уверен, что лимит строк должен быть таким коротким (вы можете читать только 78-символьные строки, а также новую строку плюс нуль в ней). Я имею тенденцию использовать цифры, такие как 4096, отчасти для значения шока. Вы можете использовать 256 здоровых. Затем вам необходимо исправить вызов 'fgets()' и 'strtok()'. Вы также должны решить, как вы будете обрабатывать возвращаемые данные вызывающей функции; вы не можете просто вернуть указатель на локальный массив (он не существует после возвращения функции). –

ответ

3

inputнеинициализированный массив указателей. Делая *input, вы получаете первый неинициализированный указатель и передаете его fgets.

Я уверен, что ты не хотел, чтобы создать массив указателей на char, а массив char:

char input[80]; 

Однако, у вас есть более серьезные проблемы, чем это, потому что вы возвращаете указатель на этот локальный массив input (ну, после описанного выше изменения), и это приводит к неопределенным поведением, потому что локальные переменные локальны, они исчезают, когда функция возвращается и оставит вас с блуждающим указателем ,

У вас есть два решения этой проблемы: первое заключается в объявлении массива в вызывающей функции и передаче его (и его размере) в функцию, как и вы передаете input и ее длину до fgets.

Второе решение состоит в том, чтобы создать массив динамически, используя malloc, а затем запомните free его, как только вы закончите с ним.

+1

Написал мой ответ, когда вы появились ... удалили меня сейчас. – Floris