October 19th, 2023

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

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.

Topics
Code

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

3 comments

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

  • Henke37

    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.

    Read more
    • Kalle Niemitalo

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

  • Antonio Rodríguez

    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.