#c #memory-leaks #linked-list #valgrind #free
#c #утечки памяти #связанный список #valgrind #Бесплатно
Вопрос:
Я использовал функцию, предоставленную моим профессором, которая вставляет данные (целые числа) в отсортированный связанный список.
void sorted_insert(int x,node_t **list)
{
node_t *q = NULL, *pq = NULL, *new_node = NULL;
q = *list;
while (q amp;amp; x > q->data)
{
pq = q;
q = q->next;
}
new_node = malloc(sizeof(node_t));
new_node->data = x;
new_node->next = q;
if (!pq) { *list = new_node; }
else { pq->next = new_node; }
}
Основные вызовы:
node_t *list = NULL
sorted_insert(x,amp;list);
Я протестировал его, сохранив 100 случайных целых чисел, и он делает то, что ожидается, поскольку числа отсортированы. Позже я использовал пользовательскую функцию free для освобождения каждого узла, например:
void free_list(node_t *list)
{
node_t *tmp = NULL;
for (; list; list = list->next)
{
tmp = list;
free(tmp);
}
return;
}
Однако, когда я анализирую программу с помощью valgrind, это показывает, что я пропускаю память в функции sorted_insert , а если быть точным, в этой строке: new_node = malloc(sizeof(node_t));
Вывод Valgrind:
==9478== 160 (16 direct, 144 indirect) bytes in 1 blocks are definitely lost in loss record 2 of 2
==9478== at 0x483C7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==9478== by 0x109270: sorted_insert (list_insert_sorted.c:23)
==9478== by 0x10938D: main (list_insert_sorted.c:55)
Почему это происходит? Что-то не так с моей бесплатной функцией? Заранее благодарю вас.
РЕДАКТИРОВАТЬ: я изменил цикл for, и даже если я не пропускаю узлы, я все еще пропускаю память.
Комментарии:
1.
list = list->next;
выполняется дважды за цикл, фактически вы освобождаете только каждый другой узел в списке.2. @PhilippGesang Это ошибка с моей стороны, я исправил ее, но я все еще протекаю…
3. непроверено: но ваша бесплатная функция
list
в качестве условия тестирования перепроверена после бесплатной второй итерации и затем не будет очищать все. Также я бы посоветовал вам удалить ненужные переменные и указатель на указатель, потому что более простой код проще отлаживать.
Ответ №1:
Ваш свободный итератор пропускает узлы, у вашего тела цикла есть list=list->next
, и у итератора тоже, поэтому это происходит дважды. вам повезло, что у вас было четное количество узлов, что позволило избежать разыменования нулевого указателя, если у вас было нечетное число.
void free_list(node_t *list)
{
node_t *tmp = list;
while(tmp)
{
list = list->next;
free(tmp);
tmp = list;
}
return;
}
Затем вы отредактировали код, чтобы удалить повторяющийся итератор, но в вашем отредактированном коде после free(tmp)
этого память list
, указывающая на, больше не действительна (тот же адрес, что и в tmp
конце концов), и ваш отредактированный код разыменовывает только что освобожденную память, на которую list
указывает итератор, поэтому попробуйте то, что я написал вместо этого.