Consider the c code:
void mycode() {
MyType* p = malloc(sizeof(MyType));
/* set the values for p and do some stuff with it */
cleanup(p);
}
void cleanup(MyType* pointer) {
free(pointer);
pointer = NULL;
}
Am I wrong in thinking that after cleanup(p);
is called, the contents of p should now be NULL? Will cleanup(MyType* pointer)
properly free the memory allocation?
I am coding my college assignment and finding that the debugger is still showing the pointer to have a memory address instead of 0x0 (or NULL) as I expect.
I am finding the memory management in C to be very complicated (I hope that's not just me). can any shed some light onto what's happening?
The function free takes a pointer as parameter and deallocates the memory region pointed to by that pointer. The memory region passed to free must be previously allocated with calloc , malloc or realloc . If the pointer is NULL , no action is taken.
Yes, when you use a free(px); call, it frees the memory that was malloc'd earlier and pointed to by px. The pointer itself, however, will continue to exist and will still have the same address. It will not automatically be changed to NULL or anything else.
No. You must not because free(ptr) is used only when pointer ptr is previously returned by any of malloc family functions. Passing free a pointer to any other object (like a variable or array element) causes undefined behaviour.
This won't work as the pointer
in cleanup()
is local, and thus assigning it NULL
is not seen by the calling function. There are two common ways of solving this.
cleanup()
as follows:void cleanup(MyType** pointer) { free(*pointer); *pointer = NULL; }
and then just call cleanup(&p)
.
#define
macro that frees the memory and cleans the pointer.If you are using C++ then there is a third way by defining cleanup()
as:
void cleanup(MyType& *pointer) { // your old code stays the same }
Yes that will free the memory correctly.
pointer
inside the cleanup function is a local variable; a copy of the value passed in stored locally for just that function.
This might add to your confusion, but you can adjust the value of the variable p
(which is local to the mycode
method) from inside the cleanup
method like so:
void cleanup(MyType** pointer) {
free(*pointer);
*pointer = NULL;
}
In this case, pointer
stores the address of the pointer. By dereferencing that, you can change the value stored at that address. And you would call the cleanup
method like so:
cleanup(&p);
(That is, you want to pass the address of the pointer, not a copy of its value.)
I will note that it is usually good practice to deal with allocation and deallocation on the same logical 'level' of the software - i.e. don't make it the callers responsibility to allocate memory and then free it inside functions. Keep it consistent and on the same level.
cleanup
will properly free p
, but it won't change its value. C is a pass-by-value language, so you can't change the caller's variable from the called function. If you want to set p
from cleanup
, you'll need to do something like:
void cleanup(MyType **pointer) {
free(*pointer);
*pointer = NULL;
}
And call it like:
cleanup(&p);
Your code is a little bit un-idiomatic, can you explain a bit better why you want to write this cleanup
function?
Yes
Yes
Yes: There is a block of memory magically produced by malloc
(3). You have assigned the address of this memory, but not the memory itself in any meaningful way, to the pointer p
which is an auto
variable in mycode()
.
Then, you pass p
to cleanup()
, by value, which will copy the pointer and, using the copy local to cleanup()
, free the block. cleanup()
then sets it's own instance of the pointer to NULL, but this is useless. Once the function is complete the parameter pointer
ceases to exist.
Back in mycode()
, you still have pointer p
holding an address, but the block is now on the free list and not terribly useful for storage until allocated again.
You may notice that you can even still store to and read back from *p,
but various amounts of downstream lossage will occur, as this block of memory now belongs to the library and you may corrupt its data structures or the data of a future owner of a malloc() block.
Carefully reading about C can give you an abstract idea of variable lifetime, but it's far easier to visualize the near-universal (for compiled languages, anyway) implementation of parameter passing and local variable allocation as stack operations. It helps to take an assembly course before the C course.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With