C код для создания ошибки сегментации связанного списка - PullRequest
0 голосов
/ 30 апреля 2020

Хорошо, так что для моей домашней работы у меня есть функция, которая создает связанный список из файла ввода, и он похож на календарь, поэтому он читает дату и заголовок из файла. Я использую головной узел, который объявлен глобально, чтобы облегчить работу с другими функциями.
Это моя структура узла:

typedef struct event_t{  
    char title[20];  
    event_date_t date;  
    struct event_t *next;  
}event_t;

event_date_t - это просто простая структура для даты. функция:

void insert_events_linked_list(FILE *file, int n){
    //printf("LL function started\n"); //self-explanatory test line
    event_t last;
    head.next = &last;
    int i;
    //This loop will create a ll of the specified length
    for(i=0; i<n; i++){
        event_t *last = malloc(sizeof(event_t));
        int title_test = fscanf(file, "%20s%*c", last->title);
        printf("%s\n", last->title); //test line to make sure names are grabbed properly
        //This skips the rest of the event and prints error message if title is too long
        if(title_test != 1){
            fscanf(file, "%*s %*d %*d");
            printf("Error: LL event %d title too long\n", i++);
            continue;
        }
        else{
            fscanf(file, "%d %d", &last->date.month, &last->date.day);
            last = last->next;
        }
    }
    printf("Loop exited");
}

Тестовая строка печатает все заголовки, но показывает ошибку сегментации и прерывается перед печатью "L oop exited"

Ответы [ 2 ]

0 голосов
/ 30 апреля 2020

В тестовой строке печатаются все заголовки, но она показывает ошибку сегментации и прерывает работу перед печатью "L oop exited"

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

Я подозреваю, что причина Loop exited не напечатана в том, что вы не завершили его с новой строкой, и поэтому printf ждет, когда вы завершите линия или звонок fflush. По умолчанию вывод printf буферизуется строка . Это одна из причин, по которой вы должны всегда использовать вместо fprintf(stderr, ...). stderr (по умолчанию) небуферизован.

Вкл. К ошибкам.

  1. У вас есть две переменные с именем last в одной области видимости. Это почти никогда не является хорошей идеей.
  2. Этот оператор:

    head.next = &last;

    назначил адрес переменной local для глобальный head указатель. После возврата текущей функции этот адрес станет недействительным, и это почти наверняка не то, что вы хотели. В частности, head.next никогда указывает на любую память, которую вы malloc (и утечка!) В l oop.

  3. Ваш l oop выглядит следующим образом:

    for (...) {
      event_t *last = malloc(sizeof(event_t));  // last->next is uninitialized
      ...
      last = last->next;  // leak the memory allocated above 
                          // by overwriting the pointer with garbage
    }
    

    Это также явно не то, что вы хотели.

Вот один из способов постепенного создания связанного списка:

   event_t **link = &head.next;

   for (...) {
     event_t *ev = calloc(...);  // Initializes ev->next to NULL.

     // Fill the rest of ev ...

     // Link it into the list:
     *link = ev;
     link = &ev->next;
   }
0 голосов
/ 30 апреля 2020

Эта строка вашего кода,

event_t *last = malloc(sizeof(event_t));

будет объявлять новый last каждый раз, когда for возвращается назад. Объявите его как static и скорректируйте свой код соответствующим образом, и проблем больше не должно быть.

Демо

for (i=0;i<5;i++){
    int x=6;
    x++;
    printf("%d ",x);
}

Вывод

7 7 7 7 7

Вы должны увидеть проблема.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...