Mikubyte
Mikubyte

Reputation: 537

Why can't I reserve two contiguous memory regions in the same allocation without reserving both with a single call?

I have two memory regions I'm allocating with VirtualAlloc: 0x1E0000 (Size: 0x39000, Reserve) and 0x219000 (Size: 0x3000, Commit). These are both within the same allocation boundary (which in this case is rounded to 0x40000 (64K*4)), and the second region starts where the first ends.

Now forget the commit part for a minute. If I MEM_RESERVE the first 0x39000 and then MEM_RESERVE the next 0x3000, I get ERROR_INVALID_ADDRESS. However, if I MEM_RESERVE both in one go, 0x39000+0x3000=0x3C000, then it works, and I can use MEM_COMMIT to commit the second region successfully.

Why is that? Why can't I reserve each part on its own instead of as one big reserved region? After reserving the first region the remaining area within the allocation (0x219000-0x21FFFF) will have the MEM_FREE state, so how come I cannot reserve the first 0x3000 of the remaining 0x7000 in the allocation boundary?

Upvotes: 0

Views: 248

Answers (2)

Harry Johnston
Harry Johnston

Reputation: 36328

You cannot have two separate reservations within the same allocation boundary.

From the documentation for VirtualAlloc:

lpAddress [in, optional] 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.

(emphasis mine)

So your request to reserve memory starting at 0x219000 actually attempts to reserve memory starting at 0x210000, which is inside the existing allocation and hence illegal.

(It should also be noted that there is no guarantee that any particular region of virtual memory will be available for you to reserve; Windows may have already reserved it for some other purpose. Best practice is to always set the lpAddress parameter to NULL, allowing Windows to choose an address for you.)

Upvotes: 4

Guvante
Guvante

Reputation: 19213

By making two reservations you are requesting that the system manage them separately however as you note they are within the same allocation boundary so are likely being managed as a single unit. If you request a part of that unit the other part just goes unused.

However if you reserve them together you are requesting they be managed together so splitting isn't necessary.

From the documentation for the method:

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.

So your second one actually reserves starting at the same location as the first.

Upvotes: 1

Related Questions