What’s the difference between setting a page’s protection to PAGE_NOACCESS and freeing it?

Raymond Chen

A customer wanted to know if, after using Virtual­Alloc with MEM_COMMIT to commit some memory, they could free parts of it by calling Virtual­Protect with PAGE_NO­ACCESS.

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_DECOMMIT 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_RELEASE), then all the associated memory in the region is decommitted as part of the release.

3 comments

Discussion is closed. Login to edit/delete existing comments.

  • Antonio Rodríguez 0

    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.

  • Henke37 0

    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.

    • Kalle Niemitalo 0

      Two options: MEM_RESET/MEM_RESET_UNDO (since Windows 8) and OfferVirtualMemory/ReclaimVirtualMemory (since Windows 8.1 Update).

Feedback usabilla icon