Search code examples
cstructheap-memorydynamic-memory-allocation

Heap not getting free in C


This is my code snippet, I'm getting error while I'm trying to free the allocated memory.

int main()
{
    int value = 10; 
    totValues = pow(2, value);
    head = (node_t *)calloc(totValues, sizeof(node_t));
    createNode(head, 10, 20);
    free(head);
}

void createList(node_t *head, int tag, int index)
{
      node_t temp = (node_t) calloc(1, sizeof(sizeof(node_t)));
      temp->tag = tag;
      temp->next = head[index];
      head[index] = temp;
      free(temp);
 }

I'm trying to free both head and temp node, but this is not working and I see errors. I'm tracing memory leaks using valgrind. Not sure what wrong I'm doing.


Solution

  • There are a few issues you have in your example. Here is a look at your code with some fixes:

    #include <math.h>
    #include <stdio.h>
    #include <stddef.h>
    #include <stdlib.h>
    
    typedef struct node {
        int tag;
        struct node* next;
    } node_t;
    
    void createList(node_t**, int, int);
    
    int main(int argc, char** argv)
    {
        int value = 10; 
        int totValues = (int)pow(2, value);
        // `head` is an array of `node_t` pointers
        // (aka. it is a `node_t**` not a `node_t*`)
        node_t** head = (node_t**)calloc(totValues, sizeof(node_t*));
        createList(head, 10, 20);
        free(head);
        return 0;
    }
    
    void createList(node_t **head, int tag, int index)
    {
        // You don't want `sizeof(sizeof(node_t))` because that is
        // equivalent to sizeof(size_t) which is implementation defined,
        // but usually equal to 4 or 8 depending on word size.
        node_t* temp = (node_t*)calloc(1, sizeof(node_t));
        temp->tag = tag;
        temp->next = head[index];
        head[index] = temp;
        // You fill `temp` with information, point a spot in `head` to
        // that pointer and then free the memory...
        // That makes no sense. Don't do it!
        free(temp);
    }
    

    It is important to remember that free doesn't recursively free memory for a double pointer: you will need to do that yourself.

    You should call free on each node in head and then on head itself:

    createList(head, 10, 20);
    free(head[20]); //Free the one node we created
    free(head); // Free the array of nodes we created
    

    and make sure you comment out or remove the free(temp); call in the createList function.

    When you run valgrind on this, there are no more memory leaks.

    ==6322== Memcheck, a memory error detector
    ==6322== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
    ==6322== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
    ==6322== Command: ./dynamic_memory
    ==6322== 
    ==6322== 
    ==6322== HEAP SUMMARY:
    ==6322==     in use at exit: 0 bytes in 0 blocks
    ==6322==   total heap usage: 2 allocs, 2 frees, 8,208 bytes allocated
    ==6322== 
    ==6322== All heap blocks were freed -- no leaks are possible
    ==6322== 
    ==6322== For counts of detected and suppressed errors, rerun with: -v
    ==6322== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)