为什么我不能在同一分配中保留两个连续的内存区域,而不通过单个调用保留这两个区域?



我有两个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 为您选择地址。

通过进行两个预留,您请求系统单独管理它们,但请注意它们位于相同的分配边界内,因此很可能作为单个单元进行管理。如果您请求该单元的一部分,则另一部分将闲置。

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

从该方法的文档:

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

因此,您的第二个实际上从与第一个相同的位置开始保留。

最新更新