I am trying to use VirtualAlloc to reserve and commit a block of memory and then again to extend that block. Unfortunately, it is returning NULL with error ERROR_INVALID_ADDRESS despite VirtualQuery saying that the address range requested is free. Here's my code:
void* allocation = VirtualAlloc(NULL, 4096, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
void* desiredNextAllocation = (char*)allocation + 4096;
MEMORY_BASIC_INFORMATION info;
size_t memory_info = VirtualQuery(desiredNextAllocation, &info, sizeof(info));
void* extended = VirtualAlloc(desiredNextAllocation, 4096, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
The first allocation returns 0x00000000000d0000. The call to VirtualQuery results in the following data in 'info':
BaseAddress 0x00000000000d1000 void *
AllocationBase 0x0000000000000000 void *
AllocationProtect 0x00000000 unsigned long
RegionSize 0x00000000000ff000 unsigned __int64
State 0x00010000 unsigned long
Protect 0x00000001 unsigned long
Type 0x00000000 unsigned long
I interpret that to mean that there are 0xff available pages beginning at 0xd1000 which are in the MEM_FREE state. So why does my attempt to commit the page at 0xd1000 fail?
I'm running Windows 7 and this is a 64 bit build.
I have read several StackOverflow posts about VirtualAlloc but they all seem to imply that this code should work as does my understanding of the documentation.
From the documentation for VirtualAlloc:
If the memory is being reserved, the specified address is rounded down to the nearest multiple of the allocation granularity.
In this case, address 0xd1000 is rounded down to address 0xd0000, which is already reserved and hence invalid.