Is it OK to free 'void*'?
Consider:
struct foo
{
int a;
int b;
};
void* p = (void*)malloc(sizeof(struct foo));
((foo*)p)-&g开发者_StackOverflowt;a; // Do something.
free(p); // Is this safe?
Yes.
malloc returns void *
and free takes void *
, so some of your casts are meaningless, and you're always freeing a void *
even if you're starting with some other sort of pointer.
Yes, it's safe. When allocating memory, the runtime library keeps track of the size of each allocation. When you call free(), it looks up the address, and if it finds an allocation for that address, the correct amount of memory is freed (the block that was allocated at that address).
Yes -- free
takes a pointer to void, so when you call it, the pointer is (implicitly) cast to a pointer to void in any case.
The rest of your code isn't quite so safe:
void* p = (void*)malloc(sizeof(foo));
You should not cast the return from malloc (in C). This can cover up the mistake of forgetting to #include <stdlib.h>
Yes. The function prototype for free
is even:
void free(void *ptr);
In C it is perfectly safe, because there are no destructors to call.
The memory system keeps track of the size of allocations.
In C++ you must delete the same type you new, including using the delete[]
operator to delete new'ed arrays.
This is just to make sure destructors are called.
Perhaps it doesn't feel safe because of the magic happening behind the scenes. The C runtime and/or the OS itself is actively tracking the memory returned by malloc including its size and location. See though it feels like you are passing a typeless pointer back to free(), you in fact passing back a reference to an object the memory manager is actively tracking.
yes it is safe.
Yes, but normally it's a sign of poor design.
malloc() is typically used to allocate buffers (large arrays of the same primitive type) or objects (structs with fields initialised). In both cases, the malloc and the free should match so,
unsigned char *rgba_buffer = malloc(width * height * 4);
/* Use the buffer here */
free(rgba_buffer);
BITSTREAM *bs = bitstream("bitfile.boin");
/* Use the bitstream here */
destroy_bitstream(bs);
typedef struct
{
FILE *fp;
unsigned char ch;
int index;
} BITSTREAM;
BITSTREAM *bitstream(const char *filename)
{
BITSTREAM *bs = malloc(sizeof(BITSTREAM));
bs->fp = fopen(filename "rb");
/* etc */
return bs;
}
void destroybitstream(BITSTREAM *bs)
{
if(bs)
{
if(bs->fp)
fclose(bs->fp);
free(bs);
}
}
In one case, malloc and free match, and in the other the allocated memory is returned. There are also secondary resources, and the constructor and destructor match. It should be rare to allocate a region of memory, but not know what it is used for. And you shouldn't be interleaving allocations and frees chaotically.
Modern C++ tightens this all up with unique pointers which "own" the object. While you can have a unique pointer to void, it would be very rare.
精彩评论