我使用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
边界?
答案 0 :(得分:4)
在同一分配范围内,您不能有两个单独的预订。
来自VirtualAlloc的文档:
lpAddress [in,optional] 要分配的区域的起始地址。 如果正在保留内存,则指定的地址向下舍入到分配粒度的最接近的倍数。
(强调我的)
因此,从0x219000
开始保留内存的请求实际上会尝试从0x210000
开始保留内存,这是在现有分配中,因此是非法的。
(还应注意,无法保证虚拟内存的任何特定区域可供您保留; Windows可能已将其保留用于其他目的。最佳做法是始终设置{{1参数lpAddress
,允许Windows为您选择地址。)
答案 1 :(得分:1)
通过进行两次预订,您要求系统单独管理它们,但是当您注意到它们位于相同的分配边界内时,可能会作为一个单元进行管理。如果您要求该单元的一部分,则其他部分将不使用。
但是,如果您将它们保留在一起,则要求它们一起管理,因此不需要拆分。
从方法的documentation:
要分配的区域的起始地址。如果正在保留内存,则将指定的地址向下舍入到分配粒度的最接近的倍数。
所以你的第二个实际上是从与第一个相同的位置开始预留。