为啥“任何 CPU(首选 32 位)”允许我在 .NET 4.5 下分配比 x86 更多的内存?
Posted
技术标签:
【中文标题】为啥“任何 CPU(首选 32 位)”允许我在 .NET 4.5 下分配比 x86 更多的内存?【英文标题】:Why does 'Any CPU (prefer 32-bit)' allow me to allocate more memory than x86 under .NET 4.5?为什么“任何 CPU(首选 32 位)”允许我在 .NET 4.5 下分配比 x86 更多的内存? 【发布时间】:2016-05-06 05:33:04 【问题描述】:根据许多 SO 答案和this widely cited blog post,为“任何 CPU”构建并选择了“首选 32 位”选项的 .NET 4.5 应用程序将在 32 位和 64 位上作为 32 位进程运行位系统(与 .NET 4.0 及更早版本不同)。 换句话说,x86 和 AnyCPU 选择了 'prefer 32-bit' 是等效的(忽略它是否可以在 ARM 上运行)。
但是,我的测试表明,在 64 位系统上,“AnyCPU 首选 32 位”应用程序(我确认它运行 32 位)可以分配比 x86 更多的内存。我编写了一个 .NET 4.5 C# 控制台应用程序,它在循环中分配 10MB 字节数组(当然保留引用),直到它遇到 OutOfMemoryException,并在具有大量 RAM 的 64 位系统上运行它。当构建为 x86 时,它分配了大约 1.2GB。构建为“任何 CPU(首选 32 位)”的相同代码最高可达 1.5GB。
为什么不一样?
【问题讨论】:
【参考方案1】:事实证明,在 Visual Studio 2015 中,构建为“AnyCPU(首选 32 位)”会在可执行文件上设置 IMAGE_FILE_LARGE_ADDRESS_AWARE 位(相当于在其上运行 editbin /LARGEADDRESSAWARE
),而对于 x86 构建则不会.这可以通过dumpbin /HEADERS
确认并查找“应用程序可以处理大型 (>2GB) 地址”这一行。
这不是 Visual Studio 2013 的情况。更改为 apparently undocumented。
理论上,这应该会给 CLR 额外的 2GB 空间。我不知道为什么可分配的内存只增加了大约 300MB。
【讨论】:
假设您将 10MB 的对象分配到一个数组或列表本身,您可能会炸毁 那个 数组。 bhrnjica.net/2012/07/22/… 设置gcAllowVeryLargeObjects
并尝试。我的猜测是你触发 List
调整其内部数组的大小并调整为“OOM”
@ChrisMarisic 我在每次迭代中创建一个新的 10MB 字节数组,并将 reference 添加到 List(以防止它们被垃圾收集)。所以 List 本身很小,只有几百个引用。以上是关于为啥“任何 CPU(首选 32 位)”允许我在 .NET 4.5 下分配比 x86 更多的内存?的主要内容,如果未能解决你的问题,请参考以下文章
为啥允许我在 C 中使用 const 限定变量作为数组大小?
为啥我在使用 CPLEX 的 Pyomo 中出现不允许的字符错误?