首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为32位视窗可执行文件使用/LARGEADDRESSAWARE的缺点?

为32位视窗可执行文件使用/LARGEADDRESSAWARE的缺点?
EN

Stack Overflow用户
提问于 2010-02-18 21:01:28
回答 3查看 27.2K关注 0票数 40

我们需要用这个标志链接我们的一个可执行文件,因为它使用了大量的内存。

但是为什么要对一个EXE文件进行特殊处理呢?为什么不在/LARGEADDRESSAWARE上实现标准化呢?

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

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-03-30 23:05:27

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

通过设置此标志,您可以向操作系统证明:

是的,我的应用程序(以及在运行时加载的所有all )可以处理高达4 GB的内存地址。

因此,不要将进程的VAS限制为2 GB,而是解锁整个范围(4 GB)。

但你真的能保证吗?

您是否对您的进程可能使用的所有系统DLL、microsoft可再发行文件和第三方模块负责?

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

即使存在这样的bug,也很难识别。他们迟早会零星地出现。这只是个时间问题。

幸运的是,windows操作系统中内置了一个非常方便的系统级开关:

出于测试目的,请使用MEM_TOP_DOWN注册表设置。

这会强制所有内存分配自上而下,而不是正常的自下而上。

代码语言:javascript
运行
复制
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management]
"AllocationPreference"=dword:00100000

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

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

附注:对于第一次分析,我强烈推荐使用工具VMmap (SysInternals)。

结论:

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

对于您自己的代码中的问题,您也许能够修复它们。

举个很明显的例子:内存指针使用无符号整数而不是有符号整数。

当遇到第三方模块的问题时,您需要请求作者修复他的错误。除非这样做,否则最好从可执行文件中删除LargeAddressAware标志。

关于测试的注释:

对于由本身未启用MemTopDown的“测试运行器”执行的单元测试,LAA注册表开关无法获得所需的结果。

请参阅:Unit Testing for x86 LargeAddressAware compatibility

PS:

从32位代码到64位代码的迁移也是非常“相关”和非常有趣的。

有关示例,请参阅:

票数 55
EN

Stack Overflow用户

发布于 2010-02-18 21:05:56

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

因此,对于微软来说,采取安全措施要容易得多,并且需要(a)需要完整的4 4Gb和(b)已经在大内存情况下开发和测试的应用程序,以简单地设置标志。

正如你已经注意到的,这并不难。

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

票数 12
EN

Stack Overflow用户

发布于 2011-01-19 20:05:02

不,在这个上下文(C/C++)中的“遗留代码”并不是唯一使用MSB指针的丑陋把戏的代码。

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

修复大部分代码的一种方法是检查并纠正所有那些无害的“混合签名和未签名”警告。它应该做了很好的工作,至少如果你还没有定义函数,其中int类型的参数实际上是一个内存长度。

然而,“遗留代码”很可能会在相当长的一段时间内正常工作,即使您什么都不修改。

只有在一个块中分配的空间超过2 Gb时,才会中断。或者当你要比较两个不相关的指针时,它们彼此之间的距离超过2 Gb。

因为从技术上讲,比较不相关的指针是一种未定义的行为,所以你不会遇到那么多这样做的代码(但你永远不能确定)。

而且通常情况下,即使您总共需要超过2 2Gb,您的程序实际上也不会进行大于2 2Gb的单次分配。事实上,在Windows中,即使使用LARGEADDRESSAWARE,默认情况下也无法分配那么多内存。您需要打乱系统DLL,以获得大于2 2Gb的连续块

但是墨菲定律说,这种代码总有一天会崩溃,只是在你启用LARGEADDRESSAWARE之后很长一段时间,没有人会记得已经做过了。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2288728

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档