When you release memory with free(a)
, you simply mark as free the address pointed to by a
, which leaves it available to be used in future malloc()
, but it does not erase that memory or make it inaccessible.
Since the pointer b
was still pointing to it, you can see (for now) the values that are there (in fact, they are still accessible through a
, since free()
does not modify that pointer , I could not even though I wanted it because I received it by copy).
If later the program made other malloc()
it would be entirely possible for that area to be reassigned, and then b
would see the new data that you were saving in it.
On some occasions, it is possible that free()
, in addition to updating the data structures that the C runtime maintains to know which addresses are free or used, make calls to the operative to effectively release that memory. In that case, the operation would update the table of pages of the system and the address in question would be really inaccessible for the program, which would generate a segfault. In general, the behavior of free()
may depend on the implementation of the compiler and the runtime. It is not guaranteed what will happen if you try to access a zone released with free()
(but it is not guaranteed, as you can see, that a protection error will be generated).