0

I have a structure as below:

struct node {
    struct node *left;
    struct node *right;
    int val;
};

and I initialize one node called new for example, sign an value to the variable int val in the structure and free the allocated space with free(new). But using printf("%d\n", new->val) still has the number. Example:

struct node *root = (struct node *)calloc(1, sizeof(struct node));
root->val = 2;
free(root);

printf("%d\n", root->val);

The output is still:

2

gcc version is 9.3.0. I really wonder why, the code above shows that, the node and val inside it is still accessible. My question is: how do I determine, if the node is "freed"? That I can use it when I remove the node from my data structure and let other functions know, that this node is no longer available.

CryForGG
  • 71
  • 6
  • 1
    You can't. If you don't want to access something, don't access it. If you don't want other programs to access it, don't export it (though they could *still* get around that if they try hard enough). C is a low level language, you cannot "deny" access to some variable. – Marco Bonelli Nov 08 '20 at 20:17
  • You cannot determine whether a pointer points to an object that has been `free`'d - you should instead set the pointer to `NULL` after freeing and check for that – UnholySheep Nov 08 '20 at 20:17
  • try it: free(root); root = NULL; the function free() does not delete the pointer, it continues to point to the original memory area – Ivan Ivanovich Nov 08 '20 at 20:19
  • ty guys, really appreciated it – CryForGG Nov 08 '20 at 20:19
  • 1
    This is interesting to read: https://stackoverflow.com/q/6441218/898348. It's not quite the same question but eventually it boils down to the same problem. Just replace "Can a local variable's memory be accessed outside its scope?" with "Can malloced memory be accessed once it has been freed?" – Jabberwocky Nov 08 '20 at 20:30

3 Answers3

4

If you free something then the memory allocated to it is marked as "unused" and may be used by others if/when a malloc type call is made. C does not wipe down this memory, it's just left as-is.

As such using an invalidated pointer may produce valid results, or it may not. It's undefined behaviour.

If you want that value to be deleted then you must do it yourself with something like bzero or memset.

tadman
  • 208,517
  • 23
  • 234
  • 262
  • `memset()` after `free()` can get optimized out. – chux - Reinstate Monica Nov 08 '20 at 20:34
  • @chux-ReinstateMonica: It can also be optimized out before `free`, of course. There is some version of `memset` or a memory-clear function for security use that the compiler knows not to optimize out if it is done before `free`. I cannot recall its name at the moment, or whether it is a GCC, Clang, Unix, or Apple extension. – Eric Postpischil Nov 08 '20 at 21:21
  • 1
    Re “If you want that value to be deleted then you must do it yourself with something like `bzero` or `memset`”: This does not work! [GCC optimizes it out.](https://godbolt.org/z/j76oTx) Because using the memory after `free` is not defined, clearing it before `free` does not have “observable behavior” different from not clearing it. – Eric Postpischil Nov 08 '20 at 21:32
3

The pointer root still contains a valid address after you call free, and until that same chunk of memory is used for some other purpose it will still contain the data you put there. If you want to make sure you can't access it again you'll need to change the contents of root - for example:

free(root);
root := NULL;

After you free a pointer the memory is still there, but it's put back into the "free memory" pool so it can be re-used for other purposes.

  • 1
    Re “The pointer `root` still contains a valid address after you call `free`”: The C standard explicitly notes this address is invalid, in C 2018 note 106: “… Among the invalid values for dereferencing a pointer by the unary `*` operator are… and the address of an object after the end of its lifetime.” Per 6.2.4 2, “… The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.” – Eric Postpischil Nov 08 '20 at 21:16
1

The system that runs your program, together with the C library functions, keeps track of the memory chunks that you allocate and free again. This is called memory management.

Memory management keeps private data structures that we as C programmers don't have access to. These data structures record which chunks of memory are in use by your program. (It's common that part of this chunk administration is kept at addresses just outside (often below) the allocated chunk.)

When you free memory, the memory management system only updates its data structures to indicate that your chunk of memory is no longer in use. Freeing memory does not clear it. A good reason why freed memory is not cleared is program performance.

In many systems each program is being assigned a private continuous block of memory. The memory management system takes a chunk from this this block when you allocate and returns the chunk to the block when you free it.

This all means that the contents of the memory you freed remains intact until your program allocates a new chunk of memory that happens to overlap your earlier freed chunk and you start overwriting your earlier data.

When you allocate a new chunk it often won't overlap with a chunk you just freed. This is due to the fact that the memory management system has algorithms in place to for example make sure that the continuous block it manages is not fragmented. Memory fragmentation occurs when small chunks of allocated memory are all over the large block of managed memory. It's a bit similar to hard disk space fragmentation where you also have a continuous space that is used and freed again.

meaning-matters
  • 21,929
  • 10
  • 82
  • 142
  • 1
    "the memory management system only updates its data structures to indicate that your chunk of memory is no longer in use." --> C does not specify that only this happens, It might clear the data, might not. Certainly code should not rely on it being cleared – chux - Reinstate Monica Nov 08 '20 at 22:59
  • @chux-ReinstateMonica True. But, which implementation do you know that clears the data? – meaning-matters Nov 08 '20 at 23:21
  • 3
    @meaning-matters: The GNU Allocator has [a feature to alter memory when allocating and freeing (`M_PERTURB`)](https://www.gnu.org/software/libc/manual/html_node/Malloc-Tunable-Parameters.html). Apple’s has `MallocScribble`. I am sure other `malloc` implementations have similar features too. – Eric Postpischil Nov 09 '20 at 01:20