为什么创建新数组会抛出OutOfMemoryException?

4
这个会抛出一个“OutOfMemoryException”的异常。
目标框架为.NET 3.5,运行在64位Windows 2008 R2 Standard上。
using System;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            byte[] test = new byte[Int32.MaxValue];
        }
    }
}

根据文档,数组长度必须是一个正的32位整数,但显然这不是唯一需要注意的限制。
为什么在这种情况下会出现内存耗尽的情况?

5
好的,你知道,这可能是因为内存不足。 - sehe
其他数据结构,如List<T>动态分配内存,虽然这可能会有一些性能劣势,但您可以避免在声明时耗尽内存。声明如此大的数组是否有原因?(我应该说“动态调整大小”而不是分配) - Charleh
@sehe - 内存确实可用,但事实证明有一个硬编码的2GB对象大小限制 - Saul
6个回答

8

那是 2GB 的 RAM。32位整数的最大值是 2147483647,转换为 MB 是 2048,即 2GB。这台机器可能实际上已经用完了内存。参见:.NET 进程可以分配的最大内存


1
几乎但不完全;问题归结为托管.NET应用程序中任何对象的2GB限制。 - Saul

6
除了明显的“内存不足”语义外,还存在稍微更微妙的堆碎片问题:可能有超过2GB的可用RAM,但它可能不是连续的。这被称为碎片化。对于dotNET,有一个堆分析器可以告诉您何时出现这种情况。

2
Eric Lippert这样表达:“内存不足”错误之所以发生,是因为进程无法在其虚拟地址空间中找到足够大的连续未使用页面来执行所请求的映射。 - Conrad Frix

1
在标准的32位系统上,由于内存大小的限制,这是不可能的。您会溢出内存。在64位系统上,这是可能的,因为您拥有更多的地址空间,但仍不建议这样做,因为您希望支持使用任何标准应用程序的32位和64位系统。

使用这段代码,即使在64位机器上仍然可能会溢出RAM。 - Pete Garafano
仍然有可能发生溢出!我只是在解释64位系统具有更大的地址空间来包含这样的请求。但这仍然是绝对不应该做的事情。 - Jason Higgins
@TheGreatCO 在一个32位系统上执行此操作会出错,而在64位系统上执行此操作可能会出错。 - Servy
是的,除非你填满整个数组,否则以那种方式创建数组会浪费内存。 - Pete Garafano

1
问题可能不是你没有可用的内存,而是你已经将内存分散得如此之多,以至于当你尝试创建数组并且必须调整大小时,没有单个可用的内存块可以容纳它。

1

Int32.MaxValue = 2 147 483 647 字节 = 2048 兆字节

请参见此链接

在“内存和地址空间限制”中查看“每个32位进程的用户模式虚拟地址空间”和“每个64位进程的用户模式虚拟地址空间”。因此,它似乎不是操作系统限制。

请参见此链接


1

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