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

C# 为什么创建新数组会抛出OutOfMemoryException?,c#,.net,arrays,memory-management,C#,.net,Arrays,Memory Management,这一个抛出了一个OutOfMemoryException 目标框架.NET 3.5,运行在64位Windows 2008 R2标准上 根据文档,数组长度必须是一个32位正整数,但显然这不是需要注意的唯一限制 为什么在这种情况下内存会耗尽?这是2GB的ram。32位整数的最大值为2147483647,转换为兆字节的最大值为2048,即2G字节。这台机器实际上可能内存不足。请参阅:在标准32位系统上,由于RAM的大小,这是不可能的。你会使内存溢出。在64位系统上,这是可能的,因为您有更多的地址空间,

这一个抛出了一个
OutOfMemoryException

目标框架.NET 3.5,运行在64位Windows 2008 R2标准上

根据文档,数组长度必须是一个32位正整数,但显然这不是需要注意的唯一限制


为什么在这种情况下内存会耗尽?

这是2GB的ram。32位整数的最大值为2147483647,转换为兆字节的最大值为2048,即2G字节。这台机器实际上可能内存不足。请参阅:

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

问题可能不是您没有“可用”内存,但是你已经将内存碎片化了很多,以至于当你试图创建数组时,它必须调整大小,没有一块可用内存可以容纳它。

除了明显的“内存不足”语义之外,还有一个稍微微妙的堆碎片化问题:可能有超过2Gb或RAM可用,但它可能不是连续的


这就是所谓的碎片化。在这种情况下,dotNET有一个堆分析器可以向您显示。

Int32.MaxValue=2147483647字节=2048MB

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


请参见

事实证明,之所以会发生这种情况,是因为在托管.NET应用程序中创建的任何对象都有一个:

在64位Windows上运行64位托管应用程序时 在操作系统中,您可以创建不超过2 GB的对象 (GB)

另请参见


您知道,它可能内存不足其他数据结构(如列表)会动态分配内存,虽然这可能会有一些性能缺点,但您可以避免在声明时内存不足。宣布如此大规模的阵列有什么理由吗?(我可能会说“动态调整大小”而不是“分配”)@sehe-内存是可用的,但实际上是硬编码的。使用此代码,您仍然可以在64位机器上溢出RAM。仍然绝对有可能溢出!我刚才提到的事实是,64位系统有更大的地址空间来容纳这样的请求。这仍然是不应该做的事情。@Greatco A 32位系统在执行此操作时会出错,64位系统在执行此操作时可能会出错。是的,这样创建数组是浪费内存的,除非您一直填充它。相反,发生“内存不足”错误是因为进程无法在其虚拟地址空间中找到足够大的连续未使用页部分来执行请求的映射。几乎是,但不是完全;问题归结为。
using System;

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