Caching, caching, caching. Oh yeah, and fragmentation.
Memory is allocated via different layers. If your application allocates memory, it will ask it to the C/C++ runtime. The C/C++ runtime will check its own datastructures for available memory, and if it doesn't have any, it will forward the call to the OS. Depending on the C/C++ runtime (and version), the C/C++ runtime data structures might be extensive, or the C/C++ runtime might simply always forward the call to the OS directly. For Microsoft Visual Studio (not using Linux at this moment, sorry), I know that:
- Older versions had quite extensive memory data structures in the C/C++ runtime
- Newer versions seem to always forward the call to the OS (Windows Heap)
This means that when deallocate memory, the C/C++ runtime might decide to keep the memory (for several reasons, including being able to return memory quicker if you decide to allocate memory again), or might return it to the OS (if it already has lots of free memory). The OS might do exactly the same: keep the memory ready in case you want to allocate it again, or mark it as deallocated immediately.
Oh yeah, fragmentation.
Memory is typically divided in pages. On Intel x86 and amd64 a page is 4KB. Every page contains some information including:
- protection rights (read-only, read-write, execute (see DEP, NoX bit)
- its actual place (physical memory, paged out to the pagefile, ...)
Suppose your application allocates 16 times 256 bytes, and you are lucky enough that all this memory is allocated within one page of 4KB. If you now free 15 of these allocations, the 16th allocation will keep the memory page allocated, preventing the OS from marking it deallocated. It's quite easy to write an application that allocates 1.5GB, and then frees 1.4GB of it, and still consume 1.5GB of memory (according to the OS).
This means that even if you deallocated all memory, there might just be some internal C/C++ runtime data structures, or some 3rd party data structures (maybe some cache) that might keep some pages allocated, although you perfectly deallocated all of your memory.