free() not deallocating memory?

2019-01-20 19:44发布

问题:

free(str);
printf("%d\n", str->listeners);

The call to printf succeeds (as do any other calls to str's members). How is this possible?

回答1:

You're just (un)lucky. That code exhibits undefined behavior - anything can happen, including looking like the memory wasn't freed.

The memory is freed, but there is no point in actively clearing it, so its original content is likely to still be there. But you can't rely on that.



回答2:

Here's an analogy for you: imagine you're renting an apartment (that's the memory) and you terminate your lease but keep a duplicate of the key (that's the pointer). You might be able to get back into the apartment later if it hasn't been torn down, if the locks haven't been changed, etc. and if you do it right away you might find things the way you left them. But it's a pretty bad idea, and in the likely case you're going to get yourself in a heap of trouble...



回答3:

That is called undefined behavior. You are dereferencing a pointer which refers to deallocated memory. Anything can happen, i.e., one cannot assume that the program will crash or anything else; the behavior is undefined.



回答4:

as long as str is not NULL and the corresponding memory has not been overwritten by some other allocation it it still works because the memory content is not changed by free (if the runtime doesn't overwrite the memory area on free). BUT this is definetly undefined behaviour and you CANNOT rely on it to work this way...



回答5:

Things to keep in mind...

  • On virtually all current operating systems, free() never returns memory to the operating system. Even if it's theoretically capable of that, it would almost never actually happen. This is because memory can only be returned in aligned pages of, generally, 4kB, because that's how the MMU works, and, should one be found, ripping it out would likely fragment a block that included memory above and below it, making the entire process counterproductive. (Fragmentation is the enemy of efficient use of dynamic memory.)
  • Also, most program just generally use more memory, so the time spent searching for something to really return to the OS would be totally wasted. If it's not given back to the OS and then protected, it won't core your program when you touch it.
  • So instead, what happens is that the block you gave to free is just put on a list or some other data structure, then possibly merged into blocks above or below it.
  • The memory is still there and accessible. Some of the block may be overwritten with pointers and other internals of the library code behind malloc() and free(). But it might not be.
  • Eventually it may be handed back elsewhere in your program. But it might not be.