Search code examples
cmallocfreedynamic-memory-allocationvoid-pointers

Freeing elements of a void pointer array


I am debugging some code written by someone else which has several memory leaks detected by Valgrind. Part of the code which I believe is causing the problems involves void pointers:

int noElements = 100;
void** ptr = malloc( noElements * sizeof(void*));
for(int i = 0; i < noElements; i++)
{
    ptr[i] = malloc(sizeof(void*));
}

//Operation filling the array and doing calculation

free(ptr); //This will not clear the underlying array causing the memory leak?

I created a small test program to check the error is where I thought it was (not freeing each ptr[i] before calling free(ptr);), but I am getting errors when trying to free elements. My test program looks like this:

int main()
{
    int num = 10000000; //Large array so I can clearly see memory usage
    void** ptr = (void**) malloc(sizeof(void*) * num);

    for (int i = 0; i < num; i++)
    {
        ptr[i] = malloc(sizeof(void*));
        ptr[i] = &i;    //If I never point elements at anything, this code works
    }

    for (int i = 0; i < num; i++)
    {       
        free(ptr[i]);       //Crashes here if the elements have been pointed at a variable
    }
    free(ptr);  

    return 0;
}

Why would calling free on each array element cause the program to crash if the pointers have actually been assigned?


Solution

  • Your pointers have been assigned a value which is not what you want.

    for (int i = 0; i < num; i++)
    {
        ptr[i] = malloc(sizeof(void*));
        ptr[i] = &i;    //If I never point elements at anything, this code works
    }
    

    First you assign a valid memory address that is returned by malloc(). This address could be free'd using free(). But then you assign another address. The address of your local variable i. This memory location was not allocated using malloc() and hence cannot be free'd. By assigning this address you've lost the dynamically allocated address causing a memory leak.

    Your comment is wrong. You already assigned a value that ptr[i] points to some valid address. You don't need to assign again. And you should not.