问题是关于.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());
}
}
答案 0 :(得分:8)
32位进程必须从可用的地址空间为阵列分配虚拟内存。默认为2千兆字节。其中包含代码和数据的混合。分配来自现有分配之间的漏洞。
此类分配总是失败,因为没有剩余的虚拟内存,它们会因为可用的漏洞不够大而失败。而你要求一个大漏洞,获得1.6千兆字节是非常罕见的,只适用于不加载任何额外DLL的非常简单的程序。一个基础不良的DLL是一个很好的方法,可以减少两个大洞,大大降低了这种分配成功的几率。更典型的首次尝试工作分配大约650兆字节。第二次分配没有失败,因为还有另一个漏洞。程序运行一段时间后,可能性大大降低,地址空间变得支离破碎。 90 MB的分配可能会失败。
您可以通过SysInternals的VMMap实用程序深入了解虚拟内存地址空间的分割方式。
一个简单的解决方法是将EXE项目的平台目标设置设置为AnyCPU,并在64位操作系统上运行该程序。它将具有可用的可寻址虚拟内存空间,您将仅受页面文件的最大允许大小和.NET 2千兆字节对象大小限制的限制。使用新的<gcAllowVeryLargeObjects>
配置元素在.NET 4.5中解决的限制。即使是32位程序也可以利用editbin.exe的/ LARGEADDRESSAWARE选项在64位操作系统上利用可用的4 GB 32位地址空间,您必须在后期构建事件中运行它。
答案 1 :(得分:0)
这是因为在为数组分配内存时,内存必须是连续的(即必须将数组分配为一个大的内存块)。即使总共有足够的空间来分配数组,如果空闲地址空间被分割,那么内存分配仍然会失败,除非这些空闲空间中的最大空间足够大于整个数组。