#c #linked-list #free #singly-linked-list
Вопрос:
typedef struct ListNode{
char data[4];
struct ListNode* link;
} listNode;
typedef struct{
listNode* head;
}linkedList_h;
void freeLinkedList_h(linkedList_h* L){
listNode *p;
while(L->head!=NULL){
p=L->head;
L->head=L->head->link;
free(p);
p=NULL;
}
}
это пример кода из моего учебника. В freeLinkedList_h, почему мы используем «p=NULL»?
Комментарии:
1. Потому что автор этой книги тайно выражал свою веру в то, что больше кода = лучший код? Для этой строки кода нет абсолютно никакой причины, и вы это заметили; реквизит. Используйте это в качестве топлива для тщательного изучения другого кода этого автора. Несвязанный
p-=L->head;
код даже не является допустимым, но я предполагаю, что это была опечатка (для справки, опечатки невозможны , когда вы копируете вставляете рабочий код , а не вводите вручную несвязанный, непроверенный код в редакторе SO).2.
p-=L->head
что за проклятие?3. p-=L->голова-это моя опечатка. Сри
Ответ №1:
Если p
это значение не установлено NULL
, программа будет немного более восприимчива к ошибке использования после освобождения. Это будет в гораздо большей степени зависеть от конкретной реализации распределения памяти, а также защиты системы.
При установке указателя на NULL
программу повышается вероятность жесткого сбоя, что во многих случаях предпочтительнее, чем доступ к освобожденной памяти. С пользовательским распределителем памяти это может быть еще более верно, потому что отладчик памяти не всегда может обнаружить проблему, в зависимости от реализации пользовательской памяти.
Для обычной программы, использующей настройки по умолчанию malloc
и друзей, в этом нет ничего такого, что не улавливал бы хороший отладчик памяти. Но определенно есть случаи, когда хорошей практикой является «очистка» используемой памяти, которая больше не нужна.
Предположим, что в вашем примере по какой-либо причине другой указатель имел ссылку на узел связанного списка и пытался получить доступ, например, к next
члену, он больше не мог случайно работать.
Но если это действительно то, что имел в виду автор, они должны были уточнить и, вероятно, также выполнить memset(p, 0, sizeof *p);
сначала. Поэтому я склонен сказать, что это не обязательно подразумевалось как хорошая практика.
Я бы скорее рекомендовал использовать отладчик памяти для обнаружения неприятных ошибок или добавлять только дополнительные инструкции в отладочные сборки.