简体   繁体   中英

Question about Windows userspace memory allocation limits

I'm trying to see the maximum address I can allocate memory at in Windows. I'm getting the max address by using GetSystemInfo , then trying to allocate one 4KB page. I'm noticing some behavior I haven't seen before, and I'm wondering if someone can explain why it's happening. So first, here's my test code:

SYSTEM_INFO info;
GetSystemInfo(&info);

PVOID base = (PUCHAR)info.lpMaximumApplicationAddress - info.dwPageSize;
SIZE_T size = info.dwPageSize;

LPVOID mem = VirtualAlloc(base, size, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);

Here are the few things I'm noticing.

  1. The size of the allocation is actually larger than the 4KB for one page, it's 64KB. Why?
  2. The base address of the allocation is 0x7ffffffe0000 . With a 64KB allocation size, the end address is 7fffffff0000 which is just one byte more than the highest user address. Isn't this going out of bounds?

I am doing this on x64 Windows.

If I could understand why this is happening that'd be great.

The size of the allocation is actually larger than the 4KB for one page, it's 64KB. Why?

You are not taking info.dwAllocationGranularity into account. The page size may be 4K, but the granularity is 64K. Page allocations must be on even multiples of the granularity. So, the base address you are specifying is being rounded down to the next lowest granularity boundary. This is discussed in the VirtualAlloc() documentation:

lpAddress

The starting address of the region to allocate. If the memory is being reserved, the specified address is rounded down to the nearest multiple of the allocation granularity . If the memory is already reserved and is being committed, the address is rounded down to the next page boundary. To determine the size of a page and the allocation granularity on the host computer, use the GetSystemInfo function. If this parameter is NULL, the system determines where to allocate the region.

Also seeWhy is address space allocation granularity 64K? .

In your case, info.lpMaximumApplicationAddress is likely 0x7FFFFFEFFFF (64K shy of 8TB, which is the max memory supported by Windows 8 and earlier; Windows 8.1 bumps that limit to 128TB). Subtracting 4K from that is 0x7FFFFFEEFFF , which then gets rounded down to 0x7FFFFFF0000 , which is an even multiple of 64K.

The base address of the allocation is 0x7ffffffe0000. With a 64KB allocation size, the end address is 7fffffff0000 which is just one byte more than the highest user address. Isn't this going out of bounds?

info.lpMaximumApplicationAddress is acting similar to a 1-past-the-end pointer for an array, or an end() iterator for a standard C++ container. It is a max address you are not supposed to go past, or even dereference. You can access memory addresses up to that max address, but not including it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM