3

I'm learning C programming and writing the basic codes like below.

I've learned that function free() can free memory allocated by calloc() and so on.

But obj->id and obj->name after executing Object_destroy have values in spite of being have executed function free().

Why does this happen? Is freeing memory not equal to deleting values?

#include <stdio.h>
#include <stdlib.h>

typedef struct Object* Object;
struct Object
{
  int id;
  char* name;
};

Object Object_new(int id, char* name)
{
  Object obj = calloc(1, sizeof(struct Object));
  obj->id = id;
  obj->name = name;
  return obj;
}

void Object_destroy(Object obj)
{
  free(obj);
}

int main()
{
  Object obj = Object_new(5, "test");

  printf("%d\n", obj->id); // => 5
  printf("%s\n", obj->name); // => test

  Object_destroy(obj);
  printf("%d\n", obj->id); // => 5
  printf("%s\n", obj->name); // => test

  return(0);
}
smci
  • 32,567
  • 20
  • 113
  • 146
  • 6
    You're accessing freed memory, which is undefined behaviour. Anything can happen, including that the code prints the values that were previously stored in the freed memory. There's nothing interesting here. You are abusing the freed memory by accessing it. – Jonathan Leffler Nov 20 '17 at 03:49
  • 4
    It does not delete the values because it is unnecessary. You are not allowed to access the memory that has been freed, so there's no point in wasting resources changing the data there. – William Pursell Nov 20 '17 at 03:55
  • 2
    Tons of duplicates: [Why are the contents pointed to by a pointer not changed when memory is deallocated using free()?)](https://stackoverflow.com/questions/11239707/why-are-the-contents-pointed-to-by-a-pointer-not-changed-when-memory-is-dealloca) , [Does free() remove the data stored in the dynamically allocated memory?](https://stackoverflow.com/questions/26183503/does-free-remove-the-data-stored-in-the-dynamically-allocated-memory) ... – smci Nov 20 '17 at 03:58
  • 1
    Because it would cost some processor time, not all user need there free memory to be clean up, this costly process is left up to the developer. – dvhh Nov 20 '17 at 03:59
  • 1
    Many implementations will typically "damage" at least part of the object when `free` is called. For example: http://coliru.stacked-crooked.com/a/da4373e4c8c37c21 - as you can see after `free` `id` becomes zero. What implementation are you using that your data survives intact? – AnT stands with Russia Nov 20 '17 at 04:02
  • 1
    Some implementation may have a debug or high security heap that may do something with the memory after you free it, but it's not required that anything is done other than to mark it as available again. – Retired Ninja Nov 20 '17 at 04:03
  • 1
    Another related question: [realloc() dangling pointers and undefined behavior](https://stackoverflow.com/questions/26072752/realloc-dangling-pointers-and-undefined-behavior). This has been asked so many times, it's time we need a canonical question-and-answer. – smci Nov 20 '17 at 04:07
  • I implemented in Apple LLVM. ~ ❯❯❯ gcc -v Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1 Apple LLVM version 8.0.0 (clang-800.0.42.1) Target: x86_64-apple-darwin15.6.0 Thread model: posix InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin – Tetsutaro Endo Nov 20 '17 at 04:10
  • I completely understand! Thank you so much!! – Tetsutaro Endo Nov 20 '17 at 04:10
  • 1
    Freeing memory is allowing something else to use it. It's like ending a lease on an apartment. You don't tear down the building afterwards; you just let someone else move in and use it. (And to keep using the memory after you freed it is just as bad keep using the apartment after your lease is over.) – ikegami Nov 20 '17 at 05:12
  • How could you know, whether the free'd memory still holds the old values? You cannot access these values without getting into the hell of undefined behaviour. – Gerhardh Nov 20 '17 at 07:28

2 Answers2

5

Think of malloc and free as signing a contract.

malloc is the promise that the chunk of memory belongs to you and won't be given to someone else. It does not guarantee anything but the size about the memory or initialize it in any way. It doesn't even prevent some other function or process from accessing that memory by address, although such access is bad behavior indeed.

free is you signing the memory back over to the allocator and nothing else. The memory is usually not "deleted" since that is a waste of cycles: the next owner will be responsible for putting in meaningful values regardless. Accessing that memory is the same sort of bad behavior as someone else accessing the memory given to you. You don't know if or when that memory is allocated elsewhere, and it's none of your business once you decide to call free.

Mad Physicist
  • 107,652
  • 25
  • 181
  • 264
1

It is called dangling pointer problem. After freeing dynamic memory, the pointer still points to that address.So, If you access value of dangling pointer, it is invoked undefined behavior.

If you avoid dangling pointer problem, then use the NULL macro. Like:

 free(obj)
 obj = NULL;
msc
  • 33,420
  • 29
  • 119
  • 214
  • Adding `obj = NULL;` to the body of `Object_destroy()` would not have changed things for OP as only the local `obj` is set to `NULL`. More/different code needed to employ this good idea. – chux - Reinstate Monica Nov 20 '17 at 16:32