1

我正在尝试创建一个用于测试的 Windows 8 32 位程序。测试包括大量分配,我遇到了麻烦。操作系统是用 /3GB 启动的,机器有 8GB 和一个页面文件,程序是用 链接的/LARGEADDRESSAWARE,所以我不应该受到内存限制。(对我来说使用 32 位程序进行测试很重要,因为某些类型的定义方式 - 例如, a size_t)。

问题是我无法从newor分配 2GB (0x80000000) 的内存VirtualAllocnew抛出bad_allocVirtualAlloc返回. NULL_ERROR_NOT_ENOUGH_MEMORY

在以前的 Windows 版本中,3GB 地址空间意味着应用程序被赋予 0x00000000 到 0xBFFFFFFF,操作系统使用 0xC0000000 到 0xFFFFFFFF(参见 Richter 的Programming Applications for Windows或 Solomon 和 Russinovich 的Windows Internals)。原则上,我相信这意味着我有理论空间。

如果我切换到 x64,一切都会按预期工作。我怀疑我遗漏了一些非常明显的东西,但我不确定是什么(比如地址空间中间的共享内存区域)。

有什么想法可以在 32 位机器上执行 0x80000000 的分配吗?

4

2 回答 2

4

在以前的 Windows 版本中,3GB 地址空间意味着应用程序被赋予 0x00000000 到 0xBFFFFFFF,操作系统使用 0xC0000000 到 0xFFFFFFFF(参见 Richter 的 Programming Applications for Windows 或 Solomon 和 Russinovich 的 Windows Internals)。原则上,我相信这意味着我有理论空间。

Windows 8 中没有任何变化。您所说的仍然是正确的。为了能够在 32 位系统上保留 2GB 内存块,您至少需要满足以下条件:

  1. 您的进程是大地址感知的。
  2. 您的系统使用 /3GB 开关启动
  3. 进程的虚拟地址空间有一个未保留的地址范围,大小为 2GB。

安排前两个条件成立很容易,但第三个条件更难控制。您不应假设您的进程将能够在 32 位进程中找到 2GB 的连续地址空间范围。这是一个不切实际的期望。

如果您的测试系统是 64 位系统,那么您也应该考虑在 32 位系统上进行测试。例如,在 64 位系统上没有 /3GB 引导选项,并且所有大地址感知 32 位进程都有 4GB 地址空间。当然,您仍然受制于我清单上的第 3 项。

于 2013-05-20T20:53:28.273 回答
2

/3GB 选项在 64 位操作系统上没有意义,并且不再支持 Vista 及更高版本。在使用 BCDEdit 的现代 32 位版本的 Windows(如 Windows 8)上,该选项是“IncreaseUserVA”。因此,您实际上不太可能得到想要的东西,很可能您实际上得到了 2 GB 的地址空间。这是为什么不能分配 2 GB 的最快解释。

32 位进程4 GB在 64 位操作系统上获得地址空间,因为操作系统不需要任何上页。您必须通过告诉操作系统您不使用不明智的指针恶作剧(例如依赖地址的高位为零)来选择加入,但需要 /LARGEADDRESSAWARE link.exe 或 editbin.exe 选项。

这仍然不意味着您可以分配 4 GB,并且您现在使用当前获得的 2 GB 地址空间也存在同样的问题。地址空间在代码和数据之间共享。只需要一个带有笨拙基地址的 DLL 就可以将可用空间一分为二。

于 2013-05-20T21:26:40.840 回答