我们需要将其中一个可执行文件与此标志链接,因为它使用了大量内存 但为什么要给一个EXE文件特殊处理。为什么不标准化/ LARGEADDRESSAWARE?
所以问题是:即使你不需要它,使用/ LARGEADDRESSAWARE也有什么问题。为什么不将它作为所有EXE文件的标准使用?
答案 0 :(得分:44)
LargeAddressAware
标志应用于您的32位可执行文件会部署滴答定时炸弹!通过设置此标志你证明操作系统:
是的,我的应用程序(以及在运行时加载的所有DLL)可以处理高达4 GB的内存地址。
所以不要将进程的VAS限制为2 GB,但要解锁全部范围(4 GB)"。
但你能真的保证吗? 您是否对您的流程可能使用的所有系统DLL,Microsoft可再发行组件和第三方模块负责?
通常,内存分配以低到高的顺序返回虚拟地址。因此,除非您的进程占用大量内存(或者它具有非常分散的虚拟地址空间),否则它将永远不会使用超过2 GB边界的地址。这是隐藏与高地址相关的错误。
如果存在此类错误,则很难识别。他们偶尔会偶尔出现'#34;迟早"。这只是一个时间问题。
幸运的是,Windows操作系统内置了一个非常方便的系统范围开关:
出于测试目的,请使用MEM_TOP_DOWN注册表设置
这会强制所有内存分配从上到下,而不是正常的自下而上。
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management]
"AllocationPreference"=dword:00100000
(这是十六进制0x100000。当然需要Windows重启)
启用此开关后,您将更快地发现问题"而不是"以后"。 理想情况下,你会从一开始就看到他们"。
旁注:首先,我强烈推荐工具VMmap
(SysInternals)。
将LAA标志应用于32位可执行文件时,必须在设置了TopDown AllocationPreference
开关的x64操作系统上对其进行全面测试。
对于您自己的代码中的问题,您可以修复它们 仅举一个非常明显的例子:使用无符号整数而不是有符号整数作为内存指针。
遇到第三方模块的问题时,您需要让作者修复他的错误。除非这样做,否则最好从可执行文件中删除LargeAddressAware标志。
有关测试的说明:
MemTopDown注册表开关未达到由"测试运行器"执行的单元测试所需的结果。本身不启用了LAA 见:Unit Testing for x86 LargeAddressAware compatibility
PS:
也非常"相关"而且非常有趣的是从32位代码迁移到64位代码
例如见:
答案 1 :(得分:11)
因为编写了大量遗留代码,期望“否定”指针无效。 32位进程的前两个Gb中的任何内容都设置了msb。
因此,微软更容易安全地使用它,并且要求应用程序(a)需要完整的4Gb并且(b)已经在大型内存场景中开发和测试,以简单地设置标志。
它不是 - 正如你所注意到的那样 - 很难。
Raymond Chen - 在他的博客The Old New Thing中 - 介绍了为所有(32位)应用程序启用它的问题。
答案 2 :(得分:6)
不,这个上下文中的“遗留代码”(C / C ++)并不是专门用指针MSB播放丑陋技巧的代码。
它还包括使用'int'来存储两个指针之间的差异或内存区域长度的所有代码,而不是使用正确的类型'size_t':被签名的'int'有31位,并且无法处理超过2 Gb的值。
解决代码的大部分问题的方法是检查并纠正那些无害的“混合已签名和未签名”警告的所有。它应该完成一项很好的工作,至少如果你没有定义函数,其中int类型的参数实际上是一个内存长度。
然而,“遗留代码”很可能显然正常工作了很长一段时间,即使你什么都不改正。
只有在一个区块中分配超过2 Gb时才会中断。或者当你比较两个彼此远离2 Gb以上的无关指针时
因为比较不相关的指针在技术上是一个未定义的行为,你不会遇到那么多的代码(但你永远无法确定)。
而且即使总共需要超过2Gb,您的程序实际上也从不进行大于此的单个分配。实际上在Windows中,即使使用LARGEADDRESSAWARE,在默认情况下,根据内存的组织方式,您也无法分配那么多。你需要将系统DLL改组以获得超过2Gb的连续块
但Murphy的法律规定,某种代码将打破一天,只是在你没有检查就启用LARGEADDRESSAWARE后会发生很长时间,并且当没有人会记住这已经完成时。