#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.
- Указатель
next
в первом элементе вашего списка (root) не указывает наNULL
, потому что он будет изменен в первомfor
цикле. Sowhile(next != NULL)
не будет работать, потому что в вашем связанном списке нет элемента, на который указываетNULL
. malloc
вернет указатель с типомvoid *
, поэтому лучше привести его к вашемуnext
.- После выполнения выделения памяти результат должен быть проверен, была ли память выделена успешно или нет. Кроме того, я бы посоветовал вам использовать
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;
}
}