A customer wanted to know if, after using VirtualÂAlloc
with MEM_
to commit some memory, they could free parts of it by calling VirtualÂProtect
with PAGE_
.
No, changing a page to no-access does not free it. It makes the page inaccessible, but it’s still there. If you can restore access later, the old contents will still be there.
SYSTEM_INFO info; GetSystemInfo(&info); // Allocate two pages of read-write data auto p = (BYTE*)VirtualAlloc( nullptr, info.dwPageSize * 2, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); // Set the first byte to 1 p[0] = 1; // Remove access from the first page DWORD prev; VirtualProtect(p, info.dwPageSize, PAGE_NOACCESS, &prev); // At this point, any access to p[0] will crash with an access violation. // Restore access to the memory. VirtualProtect(p, info.dwPageSize, PAGE_READWRITE, &prev); // The old values are still there! ASSERT(p[0] == 1);
If you want to free the memory, you can use VirtualÂFree
with the MEM_
flag.
// Allocate two pages of read-write data auto p = (BYTE*)VirtualAlloc( nullptr, info.dwPageSize * 2, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); // Set the first byte of each page to 1 p[0] = 1; p[info.dwPageSize] = 1; // Decommit the first page DWORD prev; VirtualFree(p, info.dwPageSize, MEM_DECOMMIT); // The memory is now gone! // At this point, any access to p[0] will crash with an access violation. // Commit a new page. VirtualAlloc(p, info.dwPageSize, MEM_COMMIT, PAGE_READWRITE); // The old values are gone! ASSERT(p[0] != 1); // But the second page is still good. ASSERT(p[info.dwPageSize] == 1);
If you unreserve a region of address space with VirtualÂFree(..., MEM_
, then all the associated memory in the region is decommitted as part of the release.
There is also the option to do a soft discard of the page. It may be reused at the discretion of the memory manager. But if you don't dawdle too long and are lucky, you can undiscard it, with all the contents still intact. Be a slowpoke or get unlucky and you'll just have to deal with losing the data. Naturally, this option is best used for caches and other data that can be recomputed/reloaded.
Two options: MEM_RESET/MEM_RESET_UNDO (since Windows 8) and OfferVirtualMemory/ReclaimVirtualMemory (since Windows 8.1 Update).
This is like “I have this cupboard full of rubbish, so I will solve that by nailing the doors shut”. No that’s not the solution. What you have to do is emptying the cupboard so you can put other (perhaps more useful) things on it, or maybe throwing out the whole cupboard with its contents.