Reputation: 358
I want to create a function that frees the memory pointed to by the pointer and assigns this pointer to NULL. So I have to declare the argument as void**
(an indirect pointer), I know that void*
is safe for converting pointers, and using void**
is undefined behavior. But I think that should be no problem in this situation.Will this function safely free any memory allocated by malloc()
without undefined behavior? Ask the hackers to help or suggest a better way.
C code:
#include <stdio.h>
#include <stdlib.h>
// If I use safeFree(&mac_arr); ,
// it will warn "Incompatible pointer types passing ' int **' to parameter of type ' void **'"
// So I used #define, don't care about this.
#define SAFE_FREE(p) safeFree((void **)&(p))
void safeFree(void ** ptr);
int main(void) {
int *mac_arr = malloc(sizeof *mac_arr);
SAFE_FREE(mac_arr);
return 0;
}
void safeFree(void ** ptr){
if (ptr != NULL && *ptr != NULL) {
free(*ptr);
*ptr = NULL;
}
}
Upvotes: 0
Views: 291
Reputation: 17413
The pointer types int **
and void **
are incompatible. The type cast just masks the incompatibility.
You could define:
#define SAFE_FREE(p) ((void)(free(p), (p) = NULL))
Upvotes: 4
Reputation: 222941
The behavior of such code is not defined by the C standard.
In main
, mac_arr
is an int *
. The parameter safeFree
receives is a pointer to void *
. But int *
and void *
are not compatible types as defined by the C standard. They may have different sizes, alignment requirements, and representations. So converting the address of mac_arr
from int **
to void **
and using *ptr
for an lvalue of type void *
is not portable.
It might “work” in many C implementations.
The SAFE_FREE
macro you are contemplating is not a great remedy for pointer problems. While it sets the current pointer to an object to null, it has no way of affecting other pointers to the same object, such as links in linked lists or links in other data structures.
(It also does not need to test *ptr != NULL
. free
is specified to do nothing when it is passed a null pointer, so you would just be doubling up on a test that is already performed.)
Upvotes: 6