Reputation: 80
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
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