Gravitational plate of three masses and a slashed discABC0Static engraved plate. Three-dimensional view is unavailable or reduced motion is requested.

← back to fieldarchive

archiveMar 30, 2021

Windows heap management layers

How Windows memory allocation stacks from the kernel manager through VirtualAlloc, the heap APIs, malloc/free, and new/delete — and when each layer is the wrong tool.

Windows heap management

./winHeapIMHO.png
./winHeapIMHO.png

Higher layers in the stack sit on richer implementations.


Kernel-mode memory manager

  • Owns every reservation and allocation for the OS
  • Memory-mapped files
  • Shared memory
  • Copy-on-write
  • Not directly reachable from user mode

VirtualAlloc / VirtualFree

  • Lowest-level API available in user mode
  • Calls ZwAllocateVirtualMemory, which issues a fast syscall into ring0 and hands the rest to the kernel memory manager

Two hard constraints

  • You can only allocate blocks aligned to the system allocation granularity boundary.
  • You can only allocate sizes that are multiples of that granularity.

System allocation granularity

  • GetSystemInfo returns it in dwAllocationGranularity.
  • The value depends on implementation (and hardware). On 64-bit Windows it is 0x10000 bytes (64 KB).

So if you ask VirtualAlloc for eight bytes:

void* pAddress = VirtualAlloc(NULL, 8, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

On success, pAddress is aligned to a 0x10000-byte boundary. Even though you asked for eight bytes, the committed region covers a full page (typically 4 KB; exact size is dwPageSize). The entire span from pAddress through the next 64 KB is unavailable for further allocation. Requesting eight bytes effectively burns 65,536 bytes of address space.

Replacing ordinary application allocations with VirtualAlloc is risky. Use it for specific cases — mainly large reservations.

Misusing VirtualAlloc can fragment memory badly.


HeapCreate / HeapAlloc / HeapFree / HeapDestroy

Heap APIs are essentially wrappers over VirtualAlloc.

  • HeapCreate calls VirtualAlloc (or ZwAllocateVirtualMemory) to reserve a large virtual block, then builds internal structures that track smaller allocations inside it.
  • HeapAlloc / HeapFree usually do not touch the kernel. Unless a request exceeds what HeapCreate already reserved, they carve committed pieces out of that reserved chunk.
  • HeapDestroy calls VirtualFree and releases the virtual memory for real.

Heap APIs are a solid default for ordinary application allocations of arbitrary size. The tradeoff is a bit of overhead versus raw VirtualAlloc when you only need one huge block.

You often do not need to create a heap yourself. The process usually already has one; reach it with GetProcessHeap.


malloc / free

C wrappers around the heap APIs.

Unlike HeapAlloc / HeapFree, these work when the code is compiled for Windows and when it targets other operating systems. For C, this is the recommended way to allocate and free memory.


new / delete

Higher-level C++ operators.

They are also wrappers over the heap APIs, with the C++-specific machinery for constructors, destructors, and exceptions. For C++, this is the recommended way to allocate and free objects.

related

  1. Apr 1, 2021/archiveHyper-V Ubuntu 20.04 Full-Screen Fix
  2. Mar 1, 2021/articleLinked-List Attack Surface on Intel (Structure Notes)
  3. Jan 3, 2021/archiveTLS (Thread Local Storage) Callbacks

graphfeed