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