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.
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 );