malloc: Where Does Memory Come From (and Why free() Doesn't Give It Back)?
Your program calls malloc and free millions of times a second with no system call each time, because the allocator sits between you and the OS: it buys memory wholesale in big slabs and hands you small pieces retail, tracking what's free on its own shelf.
Asking the OS for memory (via mmap or brk) is a slow system call that sets up whole pages and crosses into the kernel, so the allocator sits between your program and the OS: it buys memory wholesale in big slabs and hands out small pieces retail from its own shelf. Free blocks get sorted by size into bins for fast reuse, a too-big block gets split, and freed neighbors get coalesced back together. free() usually just restocks the allocator's own shelf rather than returning memory to the OS, which is why memory can look stuck — scattered free gaps are fragmentation, and a block nobody restocked is a leak.
Transcript
Every time your program calls malloc, something hands it a piece of memory instantly — millions of times a second, with no trip to the operating system. What is that something? And here's the weird part: when you free memory, it usually does NOT go back to the OS — it lands on a shelf. So who's handing it out?
Asking the OS for memory is a system call — it sets up whole pages and crosses into the kernel. Doing that for every little malloc would be painfully slow. So your program doesn't ask the OS each time. A piece of your own program — the allocator — stands between you and the OS.
The allocator asks the OS for one big slab of memory up front, then hands YOU small pieces out of it — no system call per allocation. It's a shopkeeper: it buys memory wholesale from the OS, then sells it to you retail off its own shelf, tracking which pieces are free.
To find a free piece fast, it sorts them by SIZE into bins. Need thirty-two bytes? Grab one from the thirty-two-byte bin — no searching. A too-big block gets split; when you free neighbors, it merges them back into a bigger one. All bookkeeping, all in your own memory.
When you free a block, it goes back on the allocator's shelf — not back to the OS — so your next malloc is instantly ready to reuse it. That's also why memory looks stuck: free gaps get scattered — fragmentation — and holding a block you forgot is a leak, though the OS gave it away long ago.
So malloc is a middleman: it buys memory from the OS in bulk, sells it to you in pieces, and keeps the whole inventory on its shelf. So next time malloc feels instant, thank the shopkeeper — it already bought the memory; it's just handing you a piece off the shelf.