Свободный связанный список в C

#c #linked-list #free

#c #связанный список #Бесплатно

Вопрос:

Привет, мне нужна помощь в освобождении моего связанного списка в C. Когда я запускаю этот код, я получаю ошибку seg 11. Все, вплоть до освобождения, работает отлично. Спасибо за вашу помощь!

 #include <stdio.h>
#include <stdlib.h>

struct node{
    int x;
    struct node *next;
};

int main(void){
    struct node *root, *next;

    root = malloc(sizeof(struct node));
    root -> x = 0;
    root -> next = NULL;

    next = root;

    for (int i = 0; i <=10; i  ){
        next -> next = malloc(sizeof(struct node));
        next -> x = i;
        next = next -> next;
    }

    next = root;

    for (int j = 0; j <= 10; j   ){
        printf("%i", next -> x);
        next = next -> next;
    }
        next = root;

    while(next != NULL){
        next = root;
        root = root -> next;
        free(next);
    }
    free(root);
}
  

Ответ №1:

В исходном коде есть несколько проблем:

1) while(next != NULL) Цикл пытается использовать уже освобожденный узел.

2) Цикл уже заботится о выпуске root ( next = root; ), поэтому нет необходимости выпускать root отдельно.

3) Для while правильной работы цикла tail / head списка должен быть правильно NULL завершен. (Я добавил это завершение в первом for цикле)

4) Предполагается, что второй цикл печатает все x значения. Этого не произошло. Счетчик был коротким на одно число.

Улучшенный вариант программы представлен ниже. Пожалуйста, проверьте также вывод программы.

 #include <stdio.h>
#include <stdlib.h>

struct node{
    int x;
    struct node *next;
};

int main(void){
    struct node *root, *next, *to_free;

    root = malloc(sizeof(struct node));                   // 1 malloc

    root->x = 777;
    root->next = NULL;

    printf("allocating memory for root. root->x = %inn", root-> x);

    next = root; // next points to "head" (root)

    for (int i = 0; i <= 10; i  ){
        next->next = malloc(sizeof(struct node));      // 11 mallocs

        printf("allocating memory for next. next->x = %in", i 1 );   

        next->next->x = i 1;                           //

        next = next->next;
        next->next = NULL;                             // list termination is needed!
    }
    printf("n");

    next = root; // next points to "head" (root)

    for (int j = 0; j <= 11; j   ){                   // 12 nodes has to be printed! 
        printf("Printing x = %in", next->x);
        next = next->next;
    }
    printf("n");

    next = root;   //  next points to "head" (root)

    while(next != NULL)         
    {   
        to_free = next;         // we will free `next` as `to_free` soon

        next = next->next;      // move to the next node   

        printf("deallocating node with x = %in", to_free->x);

       free(to_free);          // now free the remembered `next`
    }
 return 0;
}
  

Вывод:

 allocating memory for root. root->x = 777

allocating memory for next. next->x = 1
allocating memory for next. next->x = 2
allocating memory for next. next->x = 3
allocating memory for next. next->x = 4
allocating memory for next. next->x = 5
allocating memory for next. next->x = 6
allocating memory for next. next->x = 7
allocating memory for next. next->x = 8
allocating memory for next. next->x = 9
allocating memory for next. next->x = 10
allocating memory for next. next->x = 11

Printing x = 777
Printing x = 1
Printing x = 2
Printing x = 3
Printing x = 4
Printing x = 5
Printing x = 6
Printing x = 7
Printing x = 8
Printing x = 9
Printing x = 10
Printing x = 11

deallocating node with x = 777
deallocating node with x = 1
deallocating node with x = 2
deallocating node with x = 3
deallocating node with x = 4
deallocating node with x = 5
deallocating node with x = 6
deallocating node with x = 7
deallocating node with x = 8
deallocating node with x = 9
deallocating node with x = 10
deallocating node with x = 11
  

Комментарии:

1. @DMop Если вы цените мою помощь, вы могли бы поддержать мой ответ и принять его. Я был бы признателен. Если вам нужны дополнительные объяснения, дайте мне знать. Спасибо!

Ответ №2:

Ваш цикл для освобождения узлов проверяет, есть ли next NULL после его вызова free(next) .

Комментарии:

1. Я сделал первую строку цикла для free последней строкой того же цикла и все равно получил ту же ошибку. Можете ли вы помочь с этим?

2. Не видя, как вы изменили код, или не зная, в чем free проблема, на самом деле нет.

Ответ №3:

Как уже указывалось в другом ответе, приведенное free() ниже находится не в том месте, поскольку оно освобождает память, которая затем проверяется в состоянии цикла while.

 while(next != NULL){
    root = root->next;
    next = root;
    free(next);
}
  

Однако также, если переместить первый оператор этого блока в конец блока, как вы предложили в своем комментарии, ваша проблема, вероятно, заключается в том, что сам этот цикл полностью достаточен для освобождения всего списка, и поэтому оператор free(root) ПОСЛЕ цикла, вероятно, является double free, что обычно являетсяошибка. Вы можете удалить его.

Комментарии:

1. Я удалил 2-й бесплатный и переместил код, как предложено в моем комментарии, но все равно получил ту же ошибку. Вы знаете, почему это может быть?

Ответ №4:

В вашем коде есть несколько проблем, которые перечислены ниже, и самая важная из них — номер 1.

  1. Указатель next в первом элементе вашего списка (root) не указывает на NULL , потому что он будет изменен в первом for цикле. So while(next != NULL) не будет работать, потому что в вашем связанном списке нет элемента, на который указывает NULL .
  2. malloc вернет указатель с типом void * , поэтому лучше привести его к вашему next .
  3. После выполнения выделения памяти результат должен быть проверен, была ли память выделена успешно или нет. Кроме того, я бы посоветовал вам использовать typedef для определения вашего связанного списка.

Ваш код должен быть таким:

 #include <stdio.h>
#include <stdlib.h>

typedef struct node{
    int x;
    struct node *next, *temp;
} node_t;

int main(int argc, char *argv[]){
  node_t *root, *next, *temp;

  root = (node_t *) malloc(sizeof(node_t));
  if(root == NULL){
    /* Do somthing */
    fprintf(stderr, "unable to allocate memoryn");
    exit(1);
  }
  root -> x = 100;
  root -> next = NULL;
  for (int i = 0; i <= 10; i  ){
    next = (node_t *) malloc(sizeof(node_t));
    if(next == NULL){
      /* Do somthing */
      fprintf(stderr, "unable to allocate memoryn");
      exit(1);
    }
    next -> x = i;
    next -> next = root;
    root = next;
  }
  temp = next;
  while(temp != NULL){
    printf("x value is: %dn", temp -> x);
    temp = temp -> next;
  }

  while(next != NULL){
    temp = next -> next;
    free(next);
    next = temp;
  }
}