Зачем использовать бесплатно, как это, в односвязном списке?

#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); сначала. Поэтому я склонен сказать, что это не обязательно подразумевалось как хорошая практика.

Я бы скорее рекомендовал использовать отладчик памяти для обнаружения неприятных ошибок или добавлять только дополнительные инструкции в отладочные сборки.