Search code examples
cvoid-pointersdouble-pointer

Automatically set pointers to NULL after free


This post shows a way to use void**s to eliminate a category of bugs related to dangling pointers (use after free, double free, etc):

void freep(void **p) {
    if (p) {
        free(*p);
        *p = NULL;
    }
}

I tried it out with the following driver code:

#include <stdlib.h>
#include <string.h>

#define free(x) freep(x)

int main(void) {
    char *s = malloc(5);
    strcpy(s, "hehe");

    char **ss = &s;

    free(s);
    free(ss);
    free(&s);
}

As noted in the post and its comments, it is technically in violation of the C standard - compiled with -Wall -Wextra -pedantic -std=c17, I get warnings regarding passing char* and char** type parameters to a void** type parameters.

My question is, can it be made to not violate the C standard, while still achieving its goal of avoiding dangling pointers by ensuring the user can't forget to set a pointer to NULL after free()-ing it?

Thank you for your time.


Solution

  • freep can only set a void * to NULL. You presumably want to set a variety of pointer types (including char *) to NULL.

    The only way freep would work is if you did

    void *p = s;
    freep( &p );
    s = p;
    

    Of course, that's ridiculous.

    An ordinary function won't do because different pointer types can have different sizes and layouts. Solution:

    #define free( p ) do { free( p ); p = NULL; } while ( 0 )
    
    free( s );
    

    Warning: The above evaluates the argument expression twice. It's better to use a name that makes it clear this is a macro rather than overridding free.

    #define SAFE_FREE( p ) do { free( p ); p = NULL; } while ( 0 )
    
    SAFE_FREE( s );