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

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

我用 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边界?

通过进行两次预订,您要求系统分别管理它们,但是正如您所注意到的,它们在同一分配范围内,因此很可能作为一个单元进行管理。如果您请求该单元的一部分,另一部分就不会被使用。

但是,如果您将它们一起预订,则表示您要求将它们一起管理,因此没有必要拆分。

来自documentation的方法:

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.

所以你的第二个实际上保留了与第一个相同的位置。

您不能在同一分配边界内有两个单独的预留。

来自 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.

(强调我的)

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

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