Search code examples
cpointersdangling-pointerdouble-free

Dangling pointers and double free


After some painful experiences, I understand the problem of dangling pointers and double free. I am seeking proper solutions.

aStruct has a number of fields including other arrays.

aStruct *A = NULL, *B = NULL;
A = (aStruct*) calloc(1, sizeof(sStruct));
B = A;
free_aStruct(A);
...
// Bunch of other code in various places.
...
free_aStruct(B);

Is there any way to write free_aStruct(X) so that free_aStruct(B) exits gracefully?

void free_aStruct(aStruct *X) {
    if (X ! = NULL) {
        if (X->a != NULL) { free(X->a); x->a = NULL; }
        free(X); X = NULL;
    }
}

Doing the above only sets A = NULL when free_aStruct(A); is called. B is now dangling.

How can this situation be avoided / remedied? Is reference counting the only viable solution? Or, are there other "defensive" approaches to freeing memory, to prevent free_aStruct(B); from exploding?


Solution

  • In plain C, the most important solution to this problem is discipline, because the root of the problem is here:

    B = A;
    

    Making a copy of the pointer without changing anything within your struct, circumventing whatever you use without any warning from the compiler. You have to use something like this:

    B = getref_aStruct(A);
    

    The next important thing is to keep track of the allocations. Some things that help are clean modularization, information hiding and DRY -- Don't Repeat Yourself. You directly call calloc() to allocate the memory while you use a free_aStruct() function to free it. Better use a create_aStruct() to allocate it. This keeps things centralized and in one place only, instead of throwing memory allocations all over your codebase.

    This is a much better base for whatever memory tracking system you build on top of this.