The system doen't necessarily release the memory at the moment you ask it to. free() just tells the system that it can release the memory. What does free say after the program exits?
BTW, sizeof(char) is always 1, so it's not a useful expression.
AFAIK, free() is instantaneous. Allocated memory cannot be used for something else until it is freed, so it doesn't make sense to delay deallocation. Allocation, on the other hand, may be delayed.
That makes more sense. So what must be happening is that malloc has a MiB set aside for an allocation table to manage the memory and hasn't deallocated the table. Although that doesn't make much sense either since the program is only allocating a KiB at a time and deallocating it before allocating the next KiB, which hardly merits a MiB table. I'd like to see the result after allocating/deallocating a KiB only once.
Every malloc() does not result in a call to the operating system to allocate memory. See man 2 sbrk.
When the C++ memory manager runs out of heap space to allocate, it calls sbrk() to the kernel to request more memory. But it requests a *lot* more; not just the 12 bytes or whatever you requested, because the kernel can only give out memory to applications in units of a page at a time.
Furthermore, in some OSes (such as Linux configured with an optimistic allocation strategy), all sbrk() does is to extend the virtual address space of the application process. It does not actually allocate the physical pages behind that memory. Rather, the physical page is actually given to the process on the first access. This is why it is called an optimistic strategy--the kernel just assumes the memory will be there when you need it. This is also what makes handling out-of-memory conditions virtually impossible:
1 2 3 4 5
// This line might very well succeed (ie, not throw std::bad_alloc):
char* big_array = newchar[ 10 * 1024 * 1024 ]; // 10M
// But this line might crash because of out of memory condition:
big_array[ 0 ] = 0;
The long and short of it is that you need to understand precisely how C++'s heap manager works and how your operating system handles memory allocations in order to even stand a chance at rationalizing what is going on. Furthermore, at least on some OSes (again, my experience is with Linux), the amount of free memory reported by the OS is totally useless. You can write a program that attempts to malloc pages at a time until the free memory reaches zero, but you'll find that the program gets killed by the OOM killer long before the free page count hits zero.