Two simple functions malloc
and free
must solve contradicting problems:
- Memory must be returned to the kernel as fast as possible.
- Memory allocations must be fast, so memory cannot not be returned to the kernel immediately and should be reused. Coupled with memory fragmentation, this makes it impossible to return memory to the kernel (glibc doesn't do this at all).
To solve both, allocators (at least glibc, musl, windows) have a threshold for a size of an allocated object: allocations greater than that size are done by direct call to mmap
/VirtualAlloc
while freeing such chunks goes directly to munmap
/VirtualFree
.
This makes it possible to keep malloc
fast for small allocations, while keeping it memory-efficient for large ones (as it can free large chunks of memory immediately).
The threshold value is usually about 128 KB and larger (see DEFAULT_MMAP_THRESHOLD_MIN
in glibc, MMAP_THRESHOLD
in musl).
Function munmap_chunk
in glibc is responsible for that and is usually called like this:
if (chunk_is_mmapped(p)) {
munmap_chunk(p);
return;
}
You will see munmap_chunk(): invalid pointer
message when passing a pointer to a chunk of memory that looks like mmap
-allocated chunk, but upon investigation has invalid size, which means there is a memory corruption or free
misusage.
Aside from this, it is also responsible of keeping track of a number of allocated through mmap
chunks to workaround VMA merging issue on Linux kernel issues.