为什么在.NET 4.5下使用“Any CPU(首选32位)”可以允许我分配比x86更多的内存?

17
根据许多SO答案和这篇广泛引用的博客文章,选择“Any CPU”并选择“prefer 32-bit”选项构建的.NET 4.5应用程序将在32位和64位系统上作为32位进程运行(与.NET 4.0及更早版本不同)。换句话说,“x86”和“AnyCPU with 'prefer 32-bit'”是等效的(忽略它是否可以在ARM上运行)。
然而,我的测试表明,在64位系统上,“AnyCPU prefer 32-bit”应用程序(我确认其运行在32位)比x86应用程序可以分配更多的内存。我编写了一个.NET 4.5 C#控制台应用程序,在循环中分配10MB字节数组(当然保持引用),直到遇到OutOfMemoryException,并在具有大量RAM的64位系统上运行。当构建为x86时,它在分配约1.2GB后崩溃。相同的代码构建为“Any CPU(prefer 32-bit)”可达到1.5GB。
为什么会有这样的差异?
1个回答

21

原来在Visual Studio 2015中,以“AnyCPU(prefer 32-bit)”方式构建会在可执行文件上设置IMAGE_FILE_LARGE_ADDRESS_AWARE位(相当于在其上运行editbin /LARGEADDRESSAWARE),而对于x86构建则不会。可以通过dumpbin /HEADERS确认,并查找“Application can handle large (>2GB) addresses”一行。

这在Visual Studio 2013中并非如此。该更改 显然未记录

理论上,这应该为CLR提供额外的2GB内存。 我不知道为什么可分配内存只增加了约300MB。


1
假设您将10MB的对象分配到数组或列表本身中,很可能会导致该数组溢出。请设置gcAllowVeryLargeObjects并尝试。我猜测您触发了List调整其内部数组大小,并且调整大小时出现了"OOM"错误。 - Chris Marisic
@ChrisMarisic 我在每次迭代中创建一个新的10MB字节数组,并将对其的引用添加到List中(以防止它们被垃圾回收)。因此,List本身很小,只有几百个引用。 - Seb Wills

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接