3

I've made a very simple linked list node structure in C, with some generic pointer data and a pointer to the next node structure. I have a function which will take a linked list node, and delete it as well as any other node it links to. It is currently made like this:

void freeLinkedList(LinkedListNode *node)
{
   LinkedListNode *currentNode = node;
   LinkedListNode *previousNode = NULL;
   do
   {
        free(currentNode->data);

        previousNode = currentNode;
        currentNode = currentNode->next;

        printf("Freeing node... %s\n", previousNode->name);
        free(previousNode);
        printf("freed it!\n");
    } while (currentNode != NULL);

    printf("Deleted node and all referencing nodes!");
}

It very simply traverses from the node given in the function, and continues to delete the pointer data, point to the next node pointed to (if any), then delete memory for the previous node. This does work as predicted... but only in some cases.

The actual LinkedList structure looks like this:

typedef struct LinkedListNode {
    void *data;
    struct LinkedListNode *next;
    char name[50];
} LinkedListNode;

In the case of structures dynamically allocated like this, the function works perfectly:

LinkedListNode *myNode1 = malloc(sizeof(struct LinkedListNode));
LinkedListNode *myNode2 = malloc(sizeof(struct LinkedListNode));
LinkedListNode *myNode3 = malloc(sizeof(struct LinkedListNode));
strcpy(myNode1->name, "Node1");
myNode1->data = NULL;
myNode1->next = myNode2;

strcpy(myNode2->name, "Node2");
myNode2->data = NULL;
myNode2->next = myNode3;

strcpy(myNode3->name, "Node3");
myNode3->data = NULL;
myNode3->next = NULL;

freeLinkedList(myNode1); // CALLING DELETE FUNCTION HERE

But if I use the function with structures allocated not on heap memory, but instead automatic stack memory like so:

LinkedListNode myNode1 = {NULL, NULL, "Node1"};
LinkedListNode myNode2 = {NULL, NULL, "Node2"};
LinkedListNode myNode3 = {NULL, NULL, "Node3"};

myNode1.next = &myNode2;
myNode2.next = &myNode3;

freeLinkedList(&myNode1); // CALLING DELETE FUNCTION HERE

I get a SIGSEGV - segmentation fault at this line in the function:

free(previousNode);

This error ONLY happens at the free function of the last node, that is, the output will say: "Freeing node... node3

Then crash.

But the very funny thing is, so far I've only experienced it using the example above. If I say, declare one more local LinkedListNode struct like this:

LinkedListNode myNode1 = {NULL, NULL, "Node1"};
LinkedListNode myNode2 = {NULL, NULL, "Node2"};
LinkedListNode myNode3 = {NULL, NULL, "Node3"};
LinkedListNode myNode4 = {NULL, NULL, "Node4"};

myNode1.next = &myNode2;
myNode2.next = &myNode3;

freeLinkedList(&myNode1);

The function actually works, and does everything as expected to.

I've tried for a couple of hours now to think of why this could be, but I'm simply stumped. Does it have something to do with me attempting to free memory allocated on the stack?

trincot
  • 317,000
  • 35
  • 244
  • 286
CodingBeagle
  • 1,888
  • 2
  • 24
  • 52
  • I wonder why freeing the NULL data pointer does not SEGV – LostBoy Aug 02 '13 at 23:47
  • Well from what I understood it when reading up on CPP reference, handing a NULL pointer to free will simply do nothing. – CodingBeagle Aug 02 '13 at 23:49
  • If the pointer passed to free is NULL no action is taken accroding to standard. – Uchia Itachi Aug 02 '13 at 23:50
  • 2
    Are you aware that you are trying to free non dynamically allocated memory in the failing example? – LostBoy Aug 02 '13 at 23:53
  • Yes, I am indeed :) That is basically what my last line of the question gestures towards: "Does it have something to do with me attempting to free memory allocated on the stack?". As this was the only thing I could come up with that might affect it... somehow :P – CodingBeagle Aug 02 '13 at 23:54
  • And it fails while freeing the first node itself! For freeing of stack memory the behavior is undefined. – Uchia Itachi Aug 02 '13 at 23:55
  • Aha, so that's basically the problem then? When I attempt to free stack memory I might be lucky it works somehow, or that it appears to be working but actually doesn't behind the scenes? And that I then in some cases will just get a crash? If freeing stack memory has undefined behaviour I suppose the non-consistent results would make sense :) – CodingBeagle Aug 02 '13 at 23:59
  • @LostBoy: `free(NULL)` is well-defined behaviour. – Oliver Charlesworth Aug 02 '13 at 23:59
  • 1
    Due to Undefined behavior anything can happen. In your case it fails at node 3 and works for 4 nodes. But, in my case it fails at the 1st node itself. – Uchia Itachi Aug 03 '13 at 00:00
  • 1
    @Bitious: Yes!, that's the explanation. – Uchia Itachi Aug 03 '13 at 00:02
  • Aha, well that makes sense then :) If any of you gentlemen would write the answer up I would be glad to accept it :) Happy to get some sort of explanation on this! Thank you both a bunch! – CodingBeagle Aug 03 '13 at 00:02
  • Well, I guess Uchia provided a far better explanation ;) – LostBoy Aug 03 '13 at 00:05

1 Answers1

2

You're a victim of Undefined behavior which is caused due to freeing of stack memory. Which can prove out to be fatal and sometimes seem to work.

This has already been answered in this thread free() on stack memory that should explain it all.

Community
  • 1
  • 1
Uchia Itachi
  • 5,287
  • 2
  • 23
  • 26
  • 2
    And just for quick reference, essentially freeing memory allocated on the stack is undefined behavior. What I did yields very unpredictable results and should simply not be done. – CodingBeagle Aug 03 '13 at 00:15