2

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

 
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());
        }
    }
4

2 回答 2

8

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

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

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

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

于 2013-02-12T14:52:38.053 回答
0

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

于 2013-02-12T13:34:56.160 回答