为啥“任何 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 更多的内存?的主要内容,如果未能解决你的问题,请参考以下文章

为啥'odeint'不允许我在这里解压浮动对象?

为啥这个程序不允许我在需要时输入信息? [复制]

为啥允许我在 C 中使用 const 限定变量作为数组大小?

为啥我在使用 CPLEX 的 Pyomo 中出现不允许的字符错误?

为啥我在这里看到“Access-Control-Allow-Origin 不允许来源”错误? [复制]

为啥我在这里看到“Access-Control-Allow-Origin 不允许来源”错误? [复制]