.NET中的数组分配

本文关键字:分配 数组 NET | 更新日期: 2023-09-27 17:58:44

问题是关于.net中数组的分配。我在下面有一个示例程序,其中我可以获得的最大数组为长度。我把长度增加到+1,它给出了内存异常。但是,如果我保持长度并删除注释,我就可以分配2个不同的大数组。两个数组都小于.net允许的2GB对象大小,并且总内存也小于虚拟内存。有人能提出什么想法吗?


class Program
    {
        static int length = 203423225;
        static double[] d = new double[length];
        //static int[] i = new int[15000000];
        static void Main(string[] args)
        {
            Console.WriteLine((sizeof(double)*(double)length)/(1024*1024));
            Console.WriteLine(d.Length);
            //Console.WriteLine(i.Length);
            Console.WriteLine(Process.GetCurrentProcess().VirtualMemorySize64.ToString());
        }
    }

.NET中的数组分配

32位进程必须从其可用的地址空间为数组分配虚拟内存。默认情况下为2GB。它包含代码和数据的混合。分配是从现有分配之间的洞中进行的。

这样的分配总是失败,不是因为没有更多的虚拟内存了,而是因为可用的漏洞不够大。如果你要求一个大漏洞,那么获得1.6个抖动字节是非常罕见的,并且只能在不加载任何额外DLL的非常简单的程序上工作。一个基础不好的DLL是一个很好的方法,可以将一个大洞一分为二,大大降低这种分配成功的几率。第一次尝试分配的更典型的工作是大约650兆字节。第二次分配没有失败,因为还有另一个洞可用。在程序运行一段时间后,地址空间变得支离破碎,几率会大大降低。90 MB的分配可能会失败。

使用SysInternals的VMMap实用程序,您可以深入了解如何为程序划分虚拟内存地址空间。

一个简单的解决方法是将EXE项目的平台目标设置设置为AnyCPU,并在64位操作系统上运行该程序。它将有大量可寻址的虚拟内存空间可用,您将仅受到页面文件的最大允许大小和.NET 2 GB对象大小限制的限制。.NET 4.5中通过新的<gcAllowVeryLargeObjects>配置元素解决了这一限制。即使是一个32位程序也可以利用64位操作系统上可用的4 GB 32位地址空间,使用editbin.exe的/LARGEADDRESSAWARE选项,您也必须在构建后事件中运行它。

这是因为在为数组分配内存时,内存必须是连续的(即数组必须作为一大块内存分配)。即使总共有足够的空间来分配阵列,如果可用地址空间被拆分,那么内存分配仍然会失败,除非这些可用空间中最大的一个足够大,用于整个阵列。