Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Free memory allocated in a different function?

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?)

like image 798
Jeff Tratner Avatar asked Jun 17 '12 12:06

Jeff Tratner


2 Answers

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.

like image 61
Oliver Charlesworth Avatar answered Sep 20 '22 15:09

Oliver Charlesworth


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).

like image 34
LihO Avatar answered Sep 19 '22 15:09

LihO