I got this message:
expected 'void **' but argument is of type 'char **'
when I tried to compile something similar to this:
void myfree( void **v )
{
if( !v || !*v )
return;
free( *v );
*v = NULL;
return;
}
I found what I think is a solution after reading this question on stack overflow:
Avoid incompatible pointer warning when dealing with double-indirection – Stack Overflow
So I adjusted to something like this:
#include <stdio.h>
#include <stdlib.h>
void myfree( void *x )
{
void **v = x;
if( !v || !*v )
return;
free( *v );
*v = NULL;
return;
}
int main( int argc, char *argv[] )
{
char *test;
if( ( test = malloc( 1 ) ) )
{
printf( "before: %p\n", test );
myfree( &test );
printf( "after: %p\n", test );
}
return 0;
}
Is this legal C? I am dereferencing a void pointer aren’t I?
Thanks guys
EDIT 12/10/2010 4:45PM EST:
As it has been pointed out free(NULL) is safe and covered by the C standard. Also, as discussed below my example above is not legal C. See caf’s answer, Zack’s answer, and my own answer.
Therefore it’s going to be easier for me to initalize any to-be-malloc’d pointers as NULL and then later on to just free() and NULL out directly in the code:
free( pointer );
pointer = NULL;
The reason I was checking for NULL in myfree() like I did was because of my experiences with fclose(). fclose(NULL) can segfault depending on platform (eg xpsp3 msvcrt.dll 7.0.2600.5512) and so I had assumed (mistakenly) the same thing could happen with free(). I had figured rather than clutter up my code with if statements I could better implement in a function.
Thanks everyone for all the good discussion
No, this is not legal C, unless you pass the address of a
void *object tomyfree()(so you might as well just keep your original definition).The reason is that in your example, an object of type
char *(the object declared astestinmain()) is modified through an lvalue of typevoid *(the lvalue*vinmyfree()). §6.5 of the C standard states:Since
void *andchar *are not compatible types, this constraint has been broken. The condition for two pointer types to be compatible is described in §6.7.5.1:To achieve the effect you want, you must use a macro:
(There is no need to check for
NULL, sincefree(NULL)is legal. Note that this macro evaluatesptwice).