2009-01-28 60 views
38

.NET數組的內存佈局是什麼?.NET數組的內存佈局

就拿此數組:

Int32[] x = new Int32[10]; 

據我所知,該陣列的體積是這樣的:

0000111122223333444455556666777788889999 

其中每個字符是一個字節,和數字對應於索引爲陣列。

此外,我知道有一種類型的參考,和一個同步塊指數對於所有對象,所以上述可調節至這樣的:

ttttssss0000111122223333444455556666777788889999 
     ^
     +- object reference points here 

另外,陣列的長度需要存儲,所以也許這是更正確的:

ttttssssllll0000111122223333444455556666777788889999 
     ^
     +- object reference points here 

這是完整的嗎?數組中是否有更多數據?

我問的原因是我們正在試圖估計一個相當大的數據語料庫的幾個不同的內存表示會花費多少內存,並且數組的大小會有很大差異,所以在一種解決方案中,開銷可能會產生很大的影響,但在另一種解決方案中可能沒有那麼大。

所以基本上,對於一個數組來說,有多少開銷,那基本上是我的問題。

而在陣列不好小隊醒來之後,這部分解決方案是靜態構建一次引用通常類型的東西,所以在這裏不需要使用可生成列表。

+1

請注意:同步塊會在methodtype引用之前出現。該變量包含一個指向方法類型引用(上面的'tttt`)的指針(引用),跳過同步塊部分。對於沒有特定尺寸或特定下限的數組,佈局實際上看起來像是`ssssttttllll000011 ... 9999NULL`。 – Abel 2009-12-09 00:27:02

回答

8

偉大的問題。我發現this文章包含值類型和引用類型的框圖。另見本article其中Ritcher規定:

[剪斷]每個陣列具有 它相關聯的一些附加 的開銷信息。此信息包含陣列的排名 (維數), 的每個維的下界(幾乎總是0)以及每個維的長度 。開銷 還包含陣列中每個元素 的類型。

+2

我可以建議將Code Project的「Arrays UNDOCUMENTED」文章添加到此解決方案中:http://www.codeproject.com/KB/dotnet/arrays.aspx – 2009-01-28 13:00:10

+2

該snip來自的書稱爲「CLR via C#」,它是一本夢幻般的書。 – 2009-01-28 19:01:06

0

一個數組對象將不得不存儲它有多少維和每個維的長度。所以至少有一個數據元素添加到您的模型

5

好問題!我想看看它自己,它似乎是一個很好的機會,嘗試Cordbg.exe的...

看來,簡單的整型數組,其格式爲:

ssssllll000011112222....nnnn0000 

s是同步塊,l數組的長度,然後是單個元素。看來終於有個0了,我不確定這是爲什麼。

對於多維數組:

ssssttttl1l1l2l2???????? 
    000011112222....nnnn000011112222....nnnn....000011112222....nnnn0000 

其中s是同步塊,叔元件的總數,L1第一維的長度,L2第二維的長度,然後兩個零?,接着依次是所有元素,最後再次爲零。

對象數組被視爲整數數組,這次的內容是引用。鋸齒形數組是指引用指向其他數組的對象數組。

17

檢查此問題的一種方法是查看WinDbg中的代碼。所以給出下面的代碼,讓我們看看它是如何出現在堆上的。

var numbers = new Int32[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 

要做的第一件事是找到實例。由於我在Main()中創建了本地地址,因此很容易找到實例的地址。

從我們可以轉儲實際實例的地址,這給了我們:

0:000> !do 0x0141ffc0 
Name: System.Int32[] 
MethodTable: 01309584 
EEClass: 01309510 
Size: 52(0x34) bytes 
Array: Rank 1, Number of elements 10, Type Int32 
Element Type: System.Int32 
Fields: 
None 

這就告訴我們,這是我們的Int32數組有10個元素和52個字節的總大小。

讓我們轉儲實例所在的內存。

0:000> d 0x0141ffc0 
0141ffc0 [84 95 30 01 0a 00 00 00-00 00 00 00 01 00 00 00 ..0............. 
0141ffd0 02 00 00 00 03 00 00 00-04 00 00 00 05 00 00 00 ................ 
0141ffe0 06 00 00 00 07 00 00 00-08 00 00 00 09 00 00 00 ................ 
0141fff0 00 00 00 00]a0 20 40 03-00 00 00 00 00 00 00 00 ..... @......... 
01420000 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 
01420010 10 6d 99 00 00 00 00 00-00 00 01 40 50 f7 3d 03 [email protected]=. 
01420020 03 00 00 00 08 00 00 00-00 01 00 00 00 00 00 00 ................ 
01420030 1c 24 40 03 00 00 00 00-00 00 00 00 00 00 00 00 [email protected] 

我已經爲52個字節插入了括號。

  • 前四個字節是在01309584.
  • 的參照方法表然後,對於所述陣列的長度四個字節。
  • 接下來是數字0到9(每四個字節)。
  • 最後四個字節爲空。我並不完全確定,但我想這必須是在實例用於鎖定時存儲對syncblock數組的引用的位置。

編輯:忘了第一篇文章的長度。

列表有些不正確,因爲romkyns指出實例實際上是從地址開始的 - 4,第一個字段是同步塊。