Jhowa
Jhowa

Reputation: 80

Linked list failing delete

I have a linked list defined like this

typedef struct Elem Elem;

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

and i wrote two list delete function the first:

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

and the second

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

So the problem is that the two function works on mac os without problems, while the second doesn't work on ubuntu, indeed when i execute it appear this error

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

So i suppose that the second is wrong, but i don't see the error

Upvotes: 0

Views: 42

Answers (1)

Vlad from Moscow
Vlad from Moscow

Reputation: 310990

The both functions are incorrect.

The first function

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

deletes only the last node in the list because deleting a node occurs only in this if statement

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

The second function is wrong because it does not set to NULL the pointer to the head node and moreover it assigns the pointer head with the address of the data member ( *head )->next while the node containing this data member is being deleted. SO the function has undefined behavior.

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

The function can be defined the following way

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

And the recursive function can look like

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

Upvotes: 1

Related Questions