40

我们需要将我们的一个可执行文件与此标志链接,因为它使用大量内存。
但是为什么要给一个EXE文件特殊处理呢。为什么不标准化/LARGEADDRESSAWARE

所以问题是:/LARGEADDRESSAWARE即使你不需要它,使用它有什么问题。为什么不将它用作所有 EXE 文件的标准?

4

3 回答 3

56

盲目地将LargeAddressAware标志应用于您的 32 位可执行文件会部署一个定时炸弹

通过设置此标志,您正在向操作系统作证:

是的,我的应用程序(以及在运行时加载的所有 DLL)可以处理高达 4 GB 的内存地址。
所以不要将进程的 VAS 限制为 2 GB,而是解锁整个范围(4 GB)”。

但你真的能保证吗?
您是否对您的进程可能使用的所有系统 DLL、Microsoft 可再发行组件和第 3 方模块负责?

通常,内存分配按从低到高的顺序返回虚拟地址。因此,除非您的进程消耗大量内存(或者它具有非常碎片化的虚拟地址空间),否则它永远不会使用超过 2 GB 边界的地址。这是隐藏与高地址相关的错误。

如果存在此类错误,则很难识别。他们会“迟早”偶尔出现。这只是时间问题。

幸运的是,windows 操作系统内置了一个非常方便的系统范围开关:
出于测试目的,请使用 MEM_TOP_DOWN 注册表设置。
这会强制所有内存分配自上而下,而不是正常的自下而上。

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management]
"AllocationPreference"=dword:00100000

(这是十六进制 0x100000。当然需要重新启动 Windows)

启用此开关后,您将“更快”而不是“稍后”识别问题。理想情况下,您会“从一开始”就看到它们。

旁注:对于第一次分析,我强烈推荐该工具VMmapSysInternals)。

结论:

将 LAA 标志应用于 32 位可执行文件时,必须在设置了 TopDownAllocationPreference开关的 x64 操作系统上对其进行全面测试。

对于您自己的代码中的问题,您可以修复它们。
举一个非常明显的例子:使用无符号整数而不是有符号整数作为内存指针。

当遇到与3rd-party模块有关的问题时,您需要要求作者修复他的错误。除非这样做,否则最好从可执行文件中删除 LargeAddressAware 标志。


关于测试的说明:

对于由本身启用 LAA的“测试运行器”执行的单元测试, MemTopDown 注册表开关没有达到预期的结果。 请参阅:x86 LargeAddressAware 兼容性的单元测试


PS:
从 32 位代码到 64 位的迁移也是非常“相关”且非常有趣的。
示例见:

于 2014-03-30T15:05:26.920 回答
12

因为许多遗留代码是在期望“负”指针无效的情况下编写的。32 位进程的前两个 Gb 中的任何内容都设置了 msb。

因此,微软更容易安全行事,并要求 (a) 需要完整 4Gb 和 (b) 已在大内存场景中开发和测试的应用程序,只需设置标志即可。

正如你所注意到的那样,这并不难。

Raymond Chen - 在他的博客The Old New Thing中- 涵盖了为所有(32 位)应用程序打开它的问题。

于 2010-02-18T13:05:56.267 回答
6

不,在这种情况下(C/C++)中的“遗留代码”并不是专门用指针的 MSB 玩丑陋把戏的代码。

它还包括所有使用'int'来存储两个指针之间的差异,或者内存区域的长度,而不是使用正确的类型'size_t'的代码:被签名的'int'有31位,无法处理超过 2 Gb 的值。

解决大部分代码的一种方法是检查它并纠正所有那些无害的“混合签名和未签名”警告。它应该可以很好地完成工作,至少如果您没有定义 int 类型的参数实际上是内存长度的函数。

但是,即使您什么都不改正,“遗留代码”也可能会在很长一段时间内正常工作。

只有在一个块中分配超过 2 Gb 时才会中断。或者当您比较两个彼此相距超过 2 Gb 的不相关指针时。
由于比较不相关的指针在技术上无论如何都是未定义的行为,因此您不会遇到那么多代码(但您永远无法确定)。
而且,即使您总共需要超过 2Gb,您的程序实际上也不会进行大于此的单个分配。事实上,在 Windows 中,即使使用 LARGEADDRESSAWARE,您也无法在默认情况下根据内存的组织方式分配那么多。您需要重新调整系统 DLL 以获得超过 2Gb 的连续块

但是墨菲定律说这种代码总有一天会被破坏,只是它会在你启用 LARGEADDRESSAWARE 之后很长时间而不检查,并且没有人会记得这已经完成。

于 2011-01-19T12:05:01.773 回答