CBFalconer <cb********@yah oo.comwrites:
Charlie Gordon wrote:
>"Tomás Ó hÉilidhe" <to*@lavabit.co ma écrit:
>>rocco.rossi :
I've been trying to write a function capable of checking if a
pointer value is set to NULL, and if it isn't, of deallocating
and setting it's value to NULL regardless of the pointer's type.
I thought "void ** " should do the trick, but I kept getting the
following warning message from gcc:
void DeallocateAndNu llify(void **const pp)
{
free (*pp);
*pp = 0;
}
Passing a null pointer to free has no effect, so there's no need
to check it for null.
You are right about free(NULL). But your solution is what the OP
tried first and it is not portable because pointer to different
types don't all have the same representation. It means that
void** may not be inappropriate to store the address of an int*.
gcc will give you a warning if you invoke
DeallocateAndN ullify(&intp) with int *intp;
No, you can pass that routine any pointer address, and it will be
auto-converted to void**. After that the free will work
correctly. Also, since void** is a pointer to void*, the NULL
assignment works. But it is more clearly written using NULL rather
than 0.
No, you can't. There is no implicit conversion to or from type
void**; there are only implicit conversions to and from type void*,
which is a distinct type.
void* is a generic pointer type. C has *no* generic
pointer-to-pointer type. Something of type void** points to an object
of type void*, and to nothing else.
One way to do what the OP wants is to use a macro, such as;
#define DEALLOCATE(p) (free(p), (p) = NULL)
This fails if the argument is an expression with side effects; the
uppercase name is a hint to avoid calling it with such an argument.
Another way is simply to set the pointer to NULL after freeing it:
free(p);
p = NULL;
or even:
free(p); p = NULL;
(The latter makes it clearer that the two statements are associated,
if you don't mind occasionally putting two statements on one line.
Possibly this could cause problems for debuggers.)
It's easy to forget to set the pointer to NULL after freeing it, but
it's also easy to forget to use DEALLOCATE() rather than free(). But
if you always want to use DEALLOCATE() rather than free(), you can
search your source code for calls to free().
Note that this will prevent some errors, but by no means all of them.
(Actually it doesn't so much prevent errors as make them easier to
detect.) But if a copy of the pointer value has been stored in another
variable, then that copy will not be set to NULL:
p = malloc(...);
p2 = p;
...
DEALLOCATE(p);
/* p == NULL */
/* p2 is indeterminate, and probably still points to the
deallocated memory */
Apart from setting its argument to NULL and evaluating its argument
twice, there is one more difference between free() and DEALLOCATE().
The argument to free() needn't be an lvalue. For example, this is
perfectly legal:
int *p = malloc(10 * sizeof *p);
/* ... */
if (p != NULL) {
p ++;
/* ... */
free(p-1);
}
This call to free() cannot legally be replaced with a call to
DEALLOCATE. Then again, I'd probably consider it poor style anyway.
I suspect that 99+% of calls to free() pass an lvalue expression that
refers to a pointer object (or whose value is NULL).
--
Keith Thompson (The_Other_Keit h) <ks***@mib.or g>
Looking for software development work in the San Diego area.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"