链表删除失败

Linked list failing delete

我有一个这样定义的链表

typedef struct Elem Elem;

struct Elem {
    int val;
    Elem *next;
};

我写了两个列表删除函数 第一个:

void free_list(Elem** head) {
        if (!*head)
            return;
        if (!(*head)->next) {
            free(*head);
            *head = 0;
            return;
        }
        free_head(&((*head)->next));
    
}

和第二个

void free_list(Elem** head) {
    while (*head) {
        Elem *tmp = *head;
        head = &((*head)->next);
        free(tmp);
    }
}

所以问题是这两个函数在 mac os 上没有问题,而第二个在 ubuntu 上不起作用,实际上当我执行它时出现这个错误

free(): double free detected in tcache 2
Aborted (core dump)

所以我认为os第二个是错误的,但我没有看到错误

这两个函数都不正确。

第一个函数

void free_head(Elem** head) {
        if (!*head)
            return;
        if (!(*head)->next) {
            free(*head);
            *head = 0;
            return;
        }
        free_head(&((*head)->next));
    
}

只删除列表中的最后一个节点,因为删除节点只发生在这个if语句中

        if (!(*head)->next) {
            free(*head);
            *head = 0;
            return;
        }

第二个函数是错误的,因为它没有将指向头节点的指针设置为NULL,而且它为指针头分配了数据成员的地址( *head )->next,而包含该数据成员的节点是被删除。所以该函数具有未定义的行为。

void free_head(Elem** head) {
    while (*head) {
        Elem *tmp = *head;
        head = &((*head)->next);
        free(tmp);
    }
}

函数可以这样定义

void free_head( Elem **head ) 
{
    while ( *head ) 
    {
        Elem *tmp = *head;
        *head = (*head)->next;
        free( tmp );
    }
}

并且递归函数可以看起来像

void free_head( Elem **head ) 
{
    if ( *head )
    {
        Elem *tmp = *head;
        *head = ( *head )->next;
        free( tmp );
        free_head( head );
    }
}