Wasted memory is a term we use to identify memory that is wasted when memory allocations are made with VirtualAlloc() that are smaller than the Windows operating system allocation granularity (which is typically 64KB).
This is best explained with an example;
ptr = VirtualAlloc(NULL, 24 * 1024, MEM_COMMIT, PAGE_READWRITE);
For example if you use VirtualAlloc() to commit 24KB of memory, VirtualAlloc() will set aside 64KB of memory, and then commit 24KB of that 64KB memory. There will be two chunks of memory as a result:
1 |
24KB |
Committed |
PAGE_READWRITE |
2 |
40KB |
Free |
PAGE_NO_ACCESS |
The first block is pointed to by the pointer returned from VirtualAlloc().
The second block isn't pointed to by anything. You can calculate where it is if you know about the allocation and the size of the allocation.
But in most cases, for this type of allocation, the second block is there implicitly - the caller probably doesn't realise they've used 64KB of memory to make that 24KB allocation.
The best way to prevent wasted memory is to use a different allocator (HeapAlloc, malloc, new, etc) to allocate the memory you need, and if you need to change the memory protection on that memory then call VirtualProtect() to change the memory protection on that memory (bear in mind this works on 4KB blocks at a minimum, aligned on 4KB page boundaries - for x86, x64 machines).
Alternatively you would write a simple memory allocator that uses VirtualAlloc() and VirtualFree() as it's backing store. You allocator would allocate when necessary using VirtualAlloc() and then subdivide those blocks to pass back suitable locations inside the larger blocks, thus avoiding the memory wastage.