Can someone explain what's wrong with it
When you have called free
on a node, you cannot access head->next
. You have to free head->next
before head
.
and what's the correct way to free linked list from memory?
A pretty elegant solution is recursion. Recursion is good for making code understandable, but unless you are aware of the dangers, avoid it in production code. I often use it for prototyping. Here is an example.
void free_list(struct node *head)
{
if(head) {
// Before freeing the first element, free the rest
free_list(head->next)
// Now it's only one element left to free
free(head);
}
}
It works like this. Let's say that we have a list: [e0, e1, e2, ..., en]
. We want to free all elements. We do that by first freeing the list [e1, e2, ..., en]
and then free the element e0
. Next step works the same way. We want to free [e1, e2, ... en]
, so we start with calling the same algorithm on the list [e2, e3, ..., en]
and when that is finished, we free e1
. The base case is when we get an empty list []
in which case we do nothing.
You can also do this non-recursively. It's not as pretty, but often more efficient and it eliminates the risk of stack overflow. This is how I would have written this in production code.
void free_list(struct node *head)
{
struct node *tmp;
while(head) {
tmp = head;
head = head->next;
free(tmp);
}
}