2013-02-12 73 views
1

問題是有關在.net中分配數組的問題。我有一個示例程序,其中最大的數組我可以得到的長度。我將長度增加到+1,它給出了內存異常。但如果我保持長度並刪除評論,我可以分配2個不同的大數組。兩個數組都少於.net允許的對象大小2 GB,並且總內存也少於虛擬內存。有人可以提出任何想法嗎?.NET中的數組分配


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

類似於http://stackoverflow.com/questions/827015/max-size-of-net-arrays – RQDQ 2013-02-12 13:11:19

+0

你期望什麼?最大數組大小取決於系統條件,並且不斷更改條件。 – 2013-02-12 13:13:15

+0

如果它是爲32位編譯的,在.NET中,你往往會在1.2-1.6GB左右出現內存不足錯誤;看到你創造了大約1.55GB的雙打,這並不奇怪。看到這個更多的信息:http://stackoverflow.com/questions/1087982/single-objects-still-limited-to-2-gb-in-size-in-clr-4-0 – 2013-02-12 13:15:01

回答

8

32位進程必須從其可用地址空間爲陣列分配虛擬內存。默認情況下爲2千兆字節。其中包含代碼和數據的混合。分配是從現有分配之間的漏洞中分配出來的。

這種分配總是失敗,不是因爲沒有更多的虛擬內存,它們失敗了,因爲可用的孔不夠大。而且你要求一個很大的漏洞,獲得1.6 jiggabytes是非常罕見的,只能在非常簡單的程序中運行,不會加載任何額外的DLL。基礎不好的DLL是削減兩個大洞的好方法,大大降低了這種分配成功的機率。更典型的第一次嘗試分配大約是650兆字節。第二次分配並沒有失敗,因爲有另一個可用的孔。程序運行一段時間後地址空間碎片化後,可能性大大降低。 90 MB的分配可能會失敗。

您可以通過SysInternals的VMMap實用程序瞭解虛擬內存地址空間是如何爲程序分割的。

一個簡單的解決方法是將EXE項目的Platform目標設置設置爲AnyCPU並在64位操作系統上運行該程序。它將具有可用的可尋址虛擬內存空間,只會受到分頁文件允許的最大大小和.NET 2 GB對象大小限制的限制。在.NET 4.5中使用新的<gcAllowVeryLargeObjects>配置元素解決了一個限制。即使32位程序也可以利用editbin.exe的/ LARGEADDRESSAWARE選項在64位操作系統上利用可用的4 GB 32位地址空間,因此您必須在後構建事件中運行它。

+0

感謝您的詳細信息。 – user1977781 2013-02-13 06:16:13

0

這將是因爲當爲數組分配內存時,內存必須是連續的(即數組必須被分配爲一大塊內存)。即使總共有足夠的空間來分配陣列,但如果空閒地址空間被拆分,那麼內存分配仍然會失敗,除非這些空閒空間中的最大空間足夠大以用於整個陣列。

+0

這似乎是有效的,但我有一個疑問。 .net中的管理堆不是連續的內存。 – user1977781 2013-02-12 14:42:29