I'm trying to learn C and I'm currently trying to write a basic stack data structure, but I can't seem to get basic malloc
/free
right.
Here's the code I've been using (I'm just posting a small part here to illustrate a specific problem, not the total code, but the error message was generated just by running this example code in valgrind
)
#include <stdio.h> #include <stdlib.h> typedef struct Entry { struct Entry *previous; int value; } Entry; void destroyEntry(Entry entry); int main(int argc, char *argv[]) { Entry* apple; apple = malloc(sizeof(Entry)); destroyEntry(*(apple)); return 0; } void destroyEntry(Entry entry) { Entry *entry_ptr = &entry; free(entry_ptr); return; }
When I run it through valgrind
with --leak-check=full --track-origins=yes
, I get the following error:
==20674== Invalid free() / delete / delete[] / realloc() ==20674== at 0x4028E58: free (vg_replace_malloc.c:427) ==20674== by 0x80485B2: destroyEntry (testing.c:53) ==20674== by 0x8048477: main (testing.c:26) ==20674== Address 0xbecc0070 is on thread 1's stack
I think this error means that the destroyEntry
function is not allowed to modify memory allocated explicitly in main. Is that right? Why can't I just free
the memory I allocated in main
in another function? (and is this behavior somehow specific to main?)
Whenever you pass a parameter to a function, a copy is made, and the function works on that copy. So in your case, you are trying to free
a copy of the original object, which doesn't make any sense.
You should modify your function to take a pointer, and then you can have it call free
directly on that pointer.
This is passing by value, which means that copy is created, thus you try to free the memory, where local variable entry
resides. Note that entry
is an object with automatic storage duration and memory where it resides will be freed automatically when your program goes out of scope of destroyEntry
function.
void destroyEntry(Entry entry) { Entry *entry_ptr = &entry; free(entry_ptr); return; }
Your function should take a pointer (passing by reference):
void destroyEntry(Entry *entry) { free(entry); }
Then instead of destroyEntry(*(apple));
you just call destroyEntry(apple);
. Note that if there is no other functionality connected with destroyEntry
function, it's redundant and it's better to just directly call free(apple)
.
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