2

I printed out a singly linked list with 1->2->3. Then I tried to free the memory of head by using free(head);, and I got 0->2->3 as the output.

I was wondering why the *next of the head node still existed after free the memory. I thought there should be nothing left in the *head when I passed to the print function.

Sorry I am new to C and memory management. Please help me with some hints if possible.

#include <stdio.h>
#include <stdlib.h>

struct ListNode{
    int val;
    struct ListNode *next;    
} ListNode;

void addNode(struct ListNode *head, int val);
void printNode(struct ListNode *head);
struct ListNode* deleteNode(struct ListNode* head, int val);

int main(int argc, char **argv){

    struct ListNode* head;
    head = (struct ListNode*)malloc(sizeof(struct ListNode));
    head->val = 1;
    addNode(head, 2);
    addNode(head, 3);

//test A: print the linked list value: 1 2 3
    printNode(head);
    printf("\n");

//test B: free memory : 0 2 3
    struct ListNode* cur = head;
    free(head);
    printNode(head);

    return 0;    
}


void addNode(struct ListNode *head, int val){
    struct ListNode* cur = head;
    while(cur->next){
        cur = cur->next;
    }
    struct ListNode* t;
    t = (struct ListNode*)malloc(sizeof(struct ListNode));
    t->val = val;

    cur->next = t;
}


void printNode(struct ListNode *head){
    struct ListNode* cur = head;
    while(cur){
        printf("%d ", cur->val);
        cur = cur->next;
    }
}
Dian Sheng
  • 47
  • 2
  • 6
    Undefined behavior for using the value of a pointer after the lifetime of the object it points to has ended. – EOF Jul 26 '16 at 17:14
  • 1
    BTW `next` of member is uninitialized. (`head->next`, `t->next`) – BLUEPIXY Jul 26 '16 at 17:16
  • Unrelated, whether you realize it or not, your `struct ListNode` declaration also declares a global variable called `ListNode`. Pretty sure your intention there was to precede all of that with `typedef` – WhozCraig Jul 26 '16 at 18:52
  • Thanks for all your comments! I really learned a lot from you guys! – Dian Sheng Jul 26 '16 at 20:34

3 Answers3

0

You need to free the allocated nodes too from the addNode() function, not just only the head node. As a newbie, start learning to use valgrind to check for memory leaks. Keep it up. Valgring quick start

jarr
  • 102
  • 2
  • 7
0

You're only referencing the head of the linked list, not the entirety of the linked list. You need to iterate through the list and free each component individually.

This should help for the code:
LinkedList - How to free the memory allocated using malloc

Community
  • 1
  • 1
slimeArmy
  • 113
  • 6
0

malloc library does its its own buffering. When we ask for a buffer of random size, it wraps the size up to a predefined size (typically next power of 2) and allots us a pre-allocated chunk of memory of the wrapped up size.

Similarly, when we free a buffer, the memory is not wiped out (contrary to our perception). The chunk of memory is just marked as "free buffer". This buffer is then used for subsequent suitable requests.

In your case, same is happening, the value field of the head is zeroized but the next field stays intact. If you write something like this,

free(head);
for(i = 0; i < 1000; i++) {
    ptr = malloc(<some random size>);
    free(ptr);
}
printNode(head);

It most likely causes the buffer to get reused which causes the buffer to get filled with junk data.

In this case, you won't be able to traverse the linked list using head.

nachiketkulk
  • 1,141
  • 11
  • 22