Zero Out Pointers to Avoid Reuse

18 Aug 2013

This week I helped my colleague resolve a memory leak problem. Of course, we used valgrind to locate where the leak was, after that, the problem became how to free the non-freed memory.

In the original code, the memory pointed by a pointer was not freed one last time outside a for loop, which is a typical case for memory leak problem. But when we tried to do just that, the program crashes at the newly introduced free(), what had happened?

The problem was, we were trying to reused a pointer that has already been freed. How to detect such situation?

In the original code, it frees memory like this:

for (int i = 0; i < some_length; ++i)
{
    if ( some_condition )
    {
        // some codes before the free
        free(pointer_to_a_object);
        // ... code to allocate new memory for 
        // ... pointer_to_a_object again
    }
    // continue with next iteration
}

free(pointer_to_a_object); // crashes the program!

This code is already problematic because it doesn’t test if pointer_to_a_object is already being freed. To test it, one instinct would be using if ( pointer_to_a_object != NULL ), but this condition only holds when the pointer is explicitly set to NULL.

So the biggest problem with this code is actually NOT ZEROING OUT POINTERS AFTER FREE/DELETE. This should be a standard practice when you write code. The following code solves the problem.

for (int i = 0; i < some_length; ++i)
{
    if ( some_condition )
    {
        // some codes before the free
        if ( pointer_to_a_object != NULL )
        {
            free(pointer_to_a_object);
            pointer_to_a_object = NULL;
        }
        // ... code to allocate new memory for 
        // ... pointer_to_a_object again
    }
    // continue with next iteration
}

if ( pointer_to_a_object != NULL )
{
    free(pointer_to_a_object); // crashes the program!
    pointer_to_a_object = NULL;
}

Because you always zero out pointers after you are done with them, you know for sure next time they are not freed yet when they are not NULL. Or, in other words, you only free pointers when they are still pointing to ‘something’. And this small tip can avoid pointers being reused. Safer code, higher assurance.