3

I wrote a simple program to test the contents of a dynamically allocated memory after free() as below. (I know we should not access the memory after free. I wrote this to check what will be there in the memory after free)

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

main()
{
    int *p = (int *)malloc(sizeof(int));

    *p = 3;
    printf("%d\n", *p);
    free(p);

    printf("%d\n", *p);
}

output: 3 0

I thought it will print either junk values or crash by 2nd print statement. But it is always printing 0.

1) Does this behaviour depend on the compiler?

2) if I try to deallocate the memory twice using free(), core dump is getting generated. In the man pages, it is mentioned that program behaviour is abnormal. But I am always getting core dump. Does this behaviour also depend on the compiler?

kadina
  • 5,042
  • 4
  • 42
  • 83
  • 2
    You can always read the spec, but if you stop to think about it; what advantage would there be? Why do extra work to initialize memory when you don't need to? FYI, your example invokes undefined behavior. – Ed S. Oct 03 '14 at 17:09
  • no. so there are some trick comes that after freeing the block but before another allocation, refer to the freed block to do something else. – Jason Hu Oct 03 '14 at 17:14
  • 1
    @HuStmpHrrr: Are you saying "no" to my UB statement? If so... no, you cannot read free'd memory. – Ed S. Oct 03 '14 at 17:36
  • @EdS. i am answering OP's question actually. well, you can read actually. it's dangerous though, so it's not recommended. and once a while, i read some examples reading freed block then do some other things. – Jason Hu Oct 03 '14 at 17:38
  • @HuStmpHrrr: It invokes undefined behavior, i.e., if you do it, your program is ill-formed and unpredictable, regardless of the circumstance. So yes, you *can* do it, but the resultant behavior will always be undefined. – Ed S. Oct 03 '14 at 18:52

4 Answers4

3

Does free() remove the data stored in the dynamically allocated memory?

No. free just free the allocated space pointed by its argument (pointer). This function accepts a char pointer to a previously allocated memory chunk, and frees it - that is, adds it to the list of free memory chunks, that may be re-allocated.
The freed memory is not cleared/erased in any manner.

You should not dereference the freed (dangling) pointer. Standard says that:

7.22.3.3 The free function:

[...] Otherwise, if the argument does not match a pointer earlier returned by a memory management function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined.

The above quote also states that freeing a pointer twice will invoke undefined behavior. Once UB is in action, you may get either expected, unexpected results. There may be program crash or core dump.

haccks
  • 104,019
  • 25
  • 176
  • 264
  • 3
    No? More like maybe, and you shouldn't care. – Deduplicator Oct 03 '14 at 17:21
  • @haccks: can you provide the link to this `7.22.3.3` – Haris Oct 03 '14 at 17:23
  • @Deduplicator; See the second point: http://csserver.evansville.edu/~amr63/linux/unix_programming/unix-memory/unix-memory.html#c_alloc_free – haccks Oct 03 '14 at 17:25
  • 1
    It could be unmapped, the text does not say. Anyway, it's about one specific allocator, which is not named, as far as I see. Others may be different, especially debug-allocators. – Deduplicator Oct 03 '14 at 17:29
  • @Deduplicator; OK. Where it is written that it may or may not alter the data ? – haccks Oct 03 '14 at 17:35
  • @haris; It is in [C11 standard](https://www.google.co.in/url?sa=t&rct=j&q=&esrc=s&source=web&cd=2&cad=rja&uact=8&ved=0CCIQFjAB&url=http%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg14%2Fwww%2Fdocs%2Fn1548.pdf&ei=4N4uVI63E4nJuASysIGACA&usg=AFQjCNFGWAb-a3SBwZiP6kQgZKqwg2OA5w&sig2=vXtY3vtWtCdjFP0bEfKjOg&bvm=bv.76802529,d.c2E) (1.67MB). – haccks Oct 03 '14 at 17:38
  • 1
    The issue is not "Where it is written that it may or may not alter the data" for @Deduplicator to cite. The issue is where is it written that supports "The freed memory is not cleared/erased in any manner." for hacck to cite. – chux - Reinstate Monica Oct 03 '14 at 17:47
  • I do see the comment that refers to "freed memory is not cleared..." in the csserver.evansville.edu link . That is _about_ Linix. It is not the spec for `free()`. – chux - Reinstate Monica Oct 03 '14 at 17:55
  • @chux; I cited from [this](http://csserver.evansville.edu/~amr63/linux/unix_programming/unix-memory/unix-memory.html#c_alloc_free) source and I still didn't find anything relevant that says anything about that it can alter the data. – haccks Oct 03 '14 at 17:57
  • @chux; `That is about Linix. It is not the spec for free()`: Well AFAIS, this is all about memory management and the line: `The freed memory is not being cleared or erased in any manner` clearly states that this is about `free`. And there is also Linux tag. – haccks Oct 03 '14 at 18:00
  • 1
    That next line says "This is why accessing memory that was just freed often does not cause a crash". Why is the word "often" there? Because, as @Deduplicator implied in a comment, the memory could be unmapped. Further it could be reused for another thread. By the time `free()` returns, the memory contents could be substantially changed. There is no spec about what the contests are or are not after a `free()` only that dereferencing a freed pointer is UB. A user can not rely on "freed memory is not cleared/erased in any manner". – chux - Reinstate Monica Oct 03 '14 at 18:09
  • On some platforms with debug build the freed memory is overwritten with a special pattern which may help finding bugs due to freed memory. – Jabberwocky Jun 22 '22 at 15:36
3

As described in gnu website

Freeing a block alters the contents of the block. Do not expect to find any data (such as a pointer to the next block in a chain of blocks) in the block after freeing it.

So, accessing a memory location after freeing it results in undefined behaviour, although free doesnt change the data in the memory location. U may be getting 0 in this example, u might as well get garbage in some other example.

And, if you try to deallocate the memory twice, on the second attempt you would be trying to free a memory which is not allocated, thats why you are gettin the core dump.

Haris
  • 12,120
  • 6
  • 43
  • 70
  • core dump? i don't think the problem will be such severe. – Jason Hu Oct 03 '14 at 17:15
  • @HuStmpHrrr: i just tried free() twice for a memory location, and this is what i got. `*** Error in `./a.out': double free or corruption (fasttop): 0x0000000001980010 *** Aborted (core dumped)` – Haris Oct 03 '14 at 17:17
  • 1
    i see. it seems glibc has this part of detection code. – Jason Hu Oct 03 '14 at 17:19
  • `Freeing a block alters the contents of the block`: Where did you read this ? – haccks Oct 03 '14 at 17:40
  • 1
    @haccks" http://www.gnu.org/software/libc/manual/html_node/Freeing-after-Malloc.html do tell me if wat i am reading is wrong. i am new to reading these in so much of detail – Haris Oct 03 '14 at 17:42
  • @haris; What written at the provided gnu link is suspicious to me. At one place it is written that: "**free can actually return memory to the operating system**". But, the fact is [**free does normally not return the memory to the operating system**](http://stackoverflow.com/a/1119334/2455888). – haccks Oct 03 '14 at 17:54
  • @haccks: that statement kinda made me think too, but then i thought may be there are some scenario where this is possible. – Haris Oct 03 '14 at 17:56
  • 2
    ["In many malloc/free implementations, free does normally not return the memory to the operating system"](http://stackoverflow.com/a/1119334/2455888) and ["free can actually return memory to the operating system"](http://stackoverflow.com/a/26183596/2410359) are _not_ contradictory. Both imply a variety of acceptable behavior. – chux - Reinstate Monica Oct 03 '14 at 18:19
1

In addition to all the above explanations for use-after-free semantics, you really may want to investigate the life-saver for every C programmer: valgrind. It will automatically detect such bugs in your code and generally save your behind in the real world. Coverity and all the other static code checkers are also great, but valgrind is awesome.

0

As far as standard C is concerned, it’s just not specified, because it is not observable. As soon as you free memory, all pointers pointing there are invalid, so there is no way to inspect that memory.*)

Even if you happen to have some standard C library documenting a certain behaviour, your compiler may still assume pointers aren’t reused after being passed to free, so you still cannot expect any particular behaviour.

*) I think, even reading these pointers is UB, not only dereferencing, but this doesn’t matter here anyway.

mafso
  • 5,433
  • 2
  • 19
  • 40