A question regarding the linked lists in C. Suppose, we have the following structures, that define the nodes in a linked list and a badly written free_list function, that (in my opinion) should cause an error:
typedef struct node *nodeT;
typedef struct node
{
int* elem;
nodeT next;
} *nodeT;
void free_list(nodeT list)
{
nodeT node;
for (node = list; node; node = node->next)
{
free(node->elem);
free(node);
}
}
As you see above, we have defined node as nodeT and a function to free the list free_list. For me, the obvious error is that inside free_list function inside for we do not have a temporary pointer to store the node value.
However, when I compile the code (on Linux), in which I create a linked list with few elements, the program doesn’t crash, it seems that everything works fine.
My question is: Is there a simple way to prove that this function (free_list) is badly written? By simple I mean setting up some compiler flags (-Wall doesn’t show any errors) or using such tools as Valgrind (used it with memcheck, that didn’t help much)?
Update: Test case as requested:
int main()
{
nodeT myType;
nodeT tmpPtr;
myType = malloc(sizeof(nodeT));
myType->item = malloc(sizeof(int));
*(myType->item) = 0;
myType->next = malloc(sizeof(nodeT));
tmpPtr = myType->next;
tmpPtr->item = malloc(sizeof(int));
*(tmpPtr->item) = 1;
tmpPtr->next = malloc(sizeof(nodeT));
tmpPtr = tmpPtr->next;
tmpPtr->item = malloc(sizeof(int));
*(tmpPtr->item) = 2;
tmpPtr->next = malloc(sizeof(nodeT));
tmpPtr = tmpPtr->next;
tmpPtr->item = malloc(sizeof(int));
*(tmpPtr->item) = 3;
tmpPtr->next = NULL;
free_list(myType);
return 0;
}
and here is the Valgrind output:
valgrind --tool=memcheck ./a.out
...
==4318== Invalid read of size 8
==4318== at 0x400579: free_list (in /home/melon/a.out)
==4318== by 0x40069E: main (in /home/melon/a.out)
==4318== Address 0x51f1048 is 0 bytes after a block of size 8 free'd
==4318== at 0x4C2A82E: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4318== by 0x400574: free_list (in /home/melon/a.out)
==4318== by 0x40069E: main (in /home/melon/a.out)
...
I’m not sure how you did the test with valgrind, but with default parameters it detects this issue just fine:
I just added this to the program to make it testable: