2009-01-28 31 views
38

Bố cục bộ nhớ của một mảng .NET là gì?Bố cục bộ nhớ của một mảng .NET

Đưa ví dụ mảng này:

Int32[] x = new Int32[10]; 

Tôi hiểu rằng phần lớn các mảng là như thế này:

0000111122223333444455556666777788889999 

đâu mỗi nhân vật là một byte, và các chữ số tương ứng với chỉ số thành mảng.

Bên cạnh đó, tôi biết rằng có một tài liệu tham khảo loại, và một syncblock-index cho tất cả các đối tượng, do đó trên có thể được điều chỉnh như sau:

ttttssss0000111122223333444455556666777788889999 
     ^
     +- object reference points here 

Bên cạnh đó, độ dài của mảng cần phải được được lưu trữ, vì vậy có lẽ điều này chính xác hơn:

ttttssssllll0000111122223333444455556666777788889999 
     ^
     +- object reference points here 

Điều này có hoàn chỉnh không? Có nhiều dữ liệu hơn trong một mảng không? Lý do tôi hỏi là chúng tôi đang cố gắng ước tính có bao nhiêu bộ nhớ khác nhau trong bộ nhớ đại diện của một kho dữ liệu khá lớn sẽ mất và kích thước của các mảng thay đổi khá một chút, do đó, các trên không có thể có tác động lớn trong một giải pháp, nhưng có lẽ không quá lớn trong một giải pháp khác.

Vì vậy, về cơ bản, đối với một mảng, có bao nhiêu chi phí ở đó, đó là cơ bản là câu hỏi của tôi.

Và trước khi các mảng là xấu đội ngũ tỉnh dậy, phần này của giải pháp là loại xây dựng tĩnh một lần-tham chiếu thường để sử dụng danh sách có thể phát triển là không cần thiết tại đây.

+1

Chỉ cần một lưu ý nhỏ: khối đồng bộ hóa xuất hiện trước tham chiếu methodtype. Biến chứa một con trỏ (tham chiếu) tới tham chiếu phương thức ('tttt' ở trên), bỏ qua phần syncblock. Bố trí thực sự trông giống như 'ssssttttllll000011 ... 9999NULL' cho mảng không có kích thước cụ thể hoặc giới hạn cụ thể thấp hơn. – Abel

Trả lời

8

Câu hỏi hay. Tôi đã tìm thấy this bài viết có chứa sơ đồ khối cho cả hai loại giá trị và loại tham chiếu. Xem thêm article này trong đó Ritcher khẳng định:

[snip] mỗi mảng có một số thông tin bổ sung trên không liên quan đến nó. Thông tin này chứa xếp hạng của mảng (số thứ nguyên), giới hạn dưới cho mỗi kích thước của mảng (hầu như luôn luôn là 0) và chiều dài của mỗi thứ nguyên. Các chi phí cũng chứa loại của mỗi phần tử trong mảng.

+2

Tôi có thể đề nghị thêm bài viết "Arrays UNDOCUMENTED" của Code Project vào giải pháp này: http://www.codeproject.com/KB/dotnet/arrays.aspx –

+2

Cuốn sách mà snip đến từ được gọi là "CLR via C#" và nó một cuốn sách tuyệt vời. –

+0

Không thể đồng ý hơn với SnOrfus - cuốn sách tuyệt vời. – ng5000

0

Đối tượng mảng sẽ phải lưu trữ số lượng thứ nguyên và chiều dài của mỗi thứ nguyên. Vì vậy, có ít nhất một phần tử dữ liệu khác để thêm vào mô hình của bạn

5

Câu hỏi hay! Tôi muốn nhìn thấy nó cho bản thân mình, và nó dường như là một cơ hội tốt để thử CorDbg.exe ...

Dường như đối với mảng số nguyên đơn giản, định dạng là:

ssssllll000011112222....nnnn0000 

đó s là khối đồng bộ, l chiều dài của mảng, và sau đó là các phần tử riêng lẻ. Dường như cuối cùng cũng có 0 ở cuối, tôi không chắc tại sao lại như thế.

Đối với mảng đa chiều:

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

đó s là khối đồng bộ, t tổng số yếu tố, L1 chiều dài của chiều đầu tiên, L2 chiều dài của chiều thứ hai, sau đó hai zero ?, tiếp theo là tất cả các phần tử tuần tự, và cuối cùng là một số không một lần nữa.

Mảng đối tượng được coi là mảng nguyên, nội dung là tham chiếu lần này. Mảng răng cưa là các mảng đối tượng nơi tham chiếu trỏ đến các mảng khác.

17

Một cách để kiểm tra điều này là xem mã trong WinDbg. Vì vậy, cho mã dưới đây, chúng ta hãy xem làm thế nào mà xuất hiện trên heap.

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

Điều đầu tiên cần làm là xác định vị trí bản sao. Vì tôi đã tạo địa chỉ này ở địa phương theo số Main(), thật dễ dàng để tìm địa chỉ của cá thể.

Từ địa chỉ chúng ta có thể đổ dụ thực tế, mang đến cho chúng ta:

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 

này cho chúng ta biết rằng đó là mảng Int32 của chúng tôi với 10 yếu tố và một tổng kích thước của 52 byte.

Hãy đổ bộ nhớ trong đó phiên bản được đặt.

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] 

Tôi đã chèn dấu ngoặc cho 52 byte.

  • Bốn byte đầu tiên là tham chiếu đến bảng phương pháp tại 01309584.
  • Sau đó bốn byte cho chiều dài của mảng.
  • Sau đó là các số từ 0 đến 9 (mỗi bốn byte).
  • Bốn byte cuối cùng là rỗng. Tôi không hoàn toàn chắc chắn, nhưng tôi đoán đó phải là nơi tham chiếu đến mảng syncblock được lưu trữ nếu cá thể được sử dụng để khóa.

Chỉnh sửa: Quên độ dài trong bài đăng đầu tiên.

Danh sách này hơi không chính xác vì vì romkyns chỉ ra trường hợp thực sự bắt đầu tại địa chỉ - 4 và trường đầu tiên là Syncblock.

+1

Bốn byte cuối cùng thực sự nằm ngoài mảng này. Điều này là do con trỏ bạn nhận được được bù đắp bởi 4 vào đối tượng; chỉ mục syncblock xuất hiện đầu tiên tại offset -4. [tham khảo] (http://msdn.microsoft.com/en-us/magazine/cc163791.aspx) –

+0

"Bốn byte đầu tiên là tham chiếu đến bảng phương thức tại 01309510." - không nên "ở số 01309584"? – stej

+0

@stej có nó nên. Cảm ơn bạn đã chỉ ra sai lầm. –

Các vấn đề liên quan