2015-01-07 3 views
1

Эта программа возвращает «Ошибка сегментации: 11» при запуске. Компилятор (GCC) не возвращает никаких ошибок или предупреждений.C - «Ошибка сегментации: 11»

#include <stdio.h> 
#include <string.h> 

typedef struct { 
    char day[3]; 
    char month[3]; 
    char year[5]; 
} DATA; 

DATA *data; 

int main() 
{ 
    FILE *file; 
    char line_buffer[BUFSIZ]; 

    if (!(file = fopen("file.dat", "rt"))) 
    { 
    printf ("Something went wrong while opening the file.\n"); 
    } 
    else 
    { 
    int line_number = 0; 

    while (fgets(line_buffer, sizeof(line_buffer), file)) 
    { 
     ++line_number; 

     if  (line_number == 1) { strncpy(data->day, line_buffer, 2); } 
     else if (line_number == 2) { strncpy(data->month, line_buffer, 2); } 
     else if (line_number == 3) { strncpy(data->year, line_buffer, 4); } 
    } 

    printf("Content: %s-%s-%s\n", data->day, data->month, data->year); 
    } 
    return 0; 
} 

Содержание file.dat является:

12 
08 
1990 

Я отлажена его с помощью GDB и это результат:

(gdb) run 
Starting program: /Users/macuser/Desktop/Primitiva/Proyecto/a.out 
Program received signal SIGSEGV, Segmentation fault. 
0x00007fff949413a0 in _dispatch_queue_attrs() from /usr/lib/system/libdispatch.dylib 

Что это значит и что я могу сделать, чтобы решить проблему? Спасибо!

ответ

2

Обратите внимание, что при использовании malloc будет работать, это ненужная дополнительная работа для вас, так как вы будете иметь, чтобы позвонить free позже, когда вам больше не нужно использовать data структуру. Но для этого вы должны сделать переменную local равной main().

Это должно решить вашу проблему

typedef struct { 
char day[3]; 
char month[3]; 
char year[5]; 
} DATA; 

DATA data; 
/*^no star here, because you don't need a pointer in your particular case */ 

int main() 
{ 
FILE *file; 
char line_buffer[BUFSIZ]; 

if (!(file = fopen("file.dat", "rt"))) 
{ 
    printf ("Something went wrong while opening the file.\n"); 
} 
else 
{ 
    int line_number = 0; 

    while (fgets(line_buffer, sizeof(line_buffer), file)) 
    { 
    ++line_number; 

    if  (line_number == 1) { strncpy(data.day, line_buffer, 2); } 
    else if (line_number == 2) { strncpy(data.month, line_buffer, 2); } 
    else if (line_number == 3) { strncpy(data.year, line_buffer, 4); } 
    } 

    printf("Content: %s-%s-%s\n", data.day, data.month, data.year); 
} 
return 0; 
} 

Вам не нужно объявлять data как указатель в данном конкретном случае, и было бы лучше, если вы этого не сделаете, пока вы не поймете, динамическое распределение памяти правильно, также переменная data не должна быть глобальной, вы можете объявить ее внутри функции main().

Неисправность сегментации вызвана неверным указатель разыменованием, если вы хотите использовать указатель, то это, как вы должны сделать это

typedef struct { 
char day[3]; 
char month[3]; 
char year[5]; 
} DATA; 

int main() 
{ 
FILE *file; 
char line_buffer[BUFSIZ]; 
if (!(file = fopen("file.dat", "rt"))) 
{ 
    printf ("Something went wrong while opening the file.\n"); 
} 
else 
{ 
    int line_number = 0; 
    DATA *data; 

    /* 
    * here data is an invalid pointer, it points nowhere. 
    * to make it valid you need malloc 
    */ 
    data = malloc(sizeof(*data)); 
    /* on failure, malloc returns NULL, for example when there is no more memory left in the system 
    * so one should check for the return value 
    */ 
    if (data == NULL) 
    { 
     fclose(file); 
     return -1; 
    } 
    /* now data is a valid pointer you can derefrence it */ 

    while (fgets(line_buffer, sizeof(line_buffer), file)) 
    { 
    ++line_number; 

    if  (line_number == 1) { strncpy(data->day, line_buffer, 2); } 
    else if (line_number == 2) { strncpy(data->month, line_buffer, 2); } 
    else if (line_number == 3) { strncpy(data->year, line_buffer, 4); } 
    } 

    printf("Content: %s-%s-%s\n", data->day, data->month, data->year); 
    /* after you have finished using the pointer, call free */ 
    free(data); 
} 
return 0; 
} 
+0

Работал! Но в чем разница между использованием указателя или отсутствием ошибки сегментации? – mariec

+0

@mariec Я не понимаю ваш вопрос. –

+0

@mariec, я обновил ответ с помощью указательной версии программы, проверил источник, у него есть комментарии, чтобы вы знали, как это работает. –

0

Вы забыли выделить память для вашей структуры

DATA *data = malloc(sizeof(DATA)); 

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

+0

Это не собирается компилировать, если OP простодушно ставит 'malloc' в его исходном коде. –

+0

@MichaelWalz Жаль, что я тебя не достал. Выделение памяти является причиной того, что он видит сбой – Gopi

+0

Это правда, но вы не можете вызвать 'malloc' (или любую другую функцию) для инициализации ** глобальной ** переменной. –

Смежные вопросы