This question already has an answer here:
- Why freed struct in C still has data? 7 answers
So, I have a struct:
tyepdef struct node {
struct node *next;
double value;
} NodeT, *NodeTP;
and I have three functions:
int deleteNode(NodeTP p)
{
free(p);
p = NULL;
return 1;
}
int deleteOne(NodeTP list)
{
if (list->next != NULL)
deleteOne(list->next);
else
deleteNode(list);
return 1;
}
int print(NodeT list)
{
printf("%lf\n", list.value);
if (list.next != NULL)
print(*list.next);
return 1;
}
deleteOne will hand the final node in the list to deleteNode so that the memory can be freed. When a node is initialized, no memory is allocated for next, until it is needed. instead, it is initially set to be NULL. This is why I don't free(p->next).
So, if I have a list of nodes (let's say their values are 3.5, 2.5, 1.2, 3.6) the print function will print the following:
3.5
2.5
1.2
3.6
Then, if the final node is deleted, and I print again, the following is printed:
3.5
2.5
1.2
3.6
If I delete another node, I get an error because I'm trying to free memory that has already been freed.
It seems as though print is accessing a memory location still, that has already been freed. However, it seems like it shouldn't be trying to read this if the 'next' node is equal to NULL. I realize this is undefined behaviour, but how can I fix this?
When the
tail node
of a linked list is deleted, it is the programmer's responsibility to set the previous' node'snext
element to NULL.When the
tail node
isfree()
ed, the memory that the node occupied will continue to hold the values it was assigned (when it was a node) until that memory is used for another purpose. Hence, it is not a good idea to continue to reference that memory after freeing it.Sometimes, I write my own
free()
function to ensure that the pointer passed to free is no longer capable of accessing the memory. Something like this:Then, when the tail node is freed, the parent node's next pointer is automatically set to NULL:
You should do this if you want NULL assigned outside the function:
And change your calls to deleteNode.