为什么我不能在同一个分配中保留两个连续的内存区域而不用一次调用来保留它们?

时间:2016-12-01 01:24:06

标签: c++ winapi memory-management allocation virtual-memory

我使用VirtualAlloc分配了两个内存区域:0x1E0000 (Size: 0x39000, Reserve)0x219000 (Size: 0x3000, Commit)。这些都在相同的分配边界内(在这种情况下舍入到0x40000 (64K*4)),第二个区域从第一个结束的地方开始。

现在忘记提交部分一分钟。如果我MEM_RESERVE第一个0x39000然后MEM_RESERVE下一个0x3000,我会ERROR_INVALID_ADDRESS。但是,如果我MEM_RESERVE同时使用0x39000+0x3000=0x3C000,那么它就可以了,我可以使用MEM_COMMIT成功提交第二个区域。

为什么?为什么我不能单独保留每个部分而不是一个大的保留区域?在保留第一个区域后,分配(0x219000-0x21FFFF)中的剩余区域将具有MEM_FREE状态,那么为什么我无法在分配中保留剩余0x3000的第一个0x7000边界?

2 个答案:

答案 0 :(得分:4)

在同一分配范围内,您不能有两个单独的预订。

来自VirtualAlloc的文档:

  

lpAddress [in,optional]   要分配的区域的起始地址。 如果正在保留内存,则指定的地址向下舍入到分配粒度的最接近的倍数。

(强调我的)

因此,从0x219000开始保留内存的请求实际上会尝试从0x210000开始保留内存,这是在现有分配中,因此是非法的。

(还应注意,无法保证虚拟内存的任何特定区域可供您保留; Windows可能已将其保留用于其他目的。最佳做法是始终设置{{1参数lpAddress,允许Windows为您选择地址。)

答案 1 :(得分:1)

通过进行两次预订,您要求系统单独管理它们,但是当您注意到它们位于相同的分配边界内时,可能会作为一个单元进行管理。如果您要求该单元的一部分,则其他部分将不使用。

但是,如果您将它们保留在一起,则要求它们一起管理,因此不需要拆分。

从方法的documentation

  

要分配的区域的起始地址。如果正在保留内存,则将指定的地址向下舍入到分配粒度的最接近的倍数。

所以你的第二个实际上是从与第一个相同的位置开始预留。