Memory layout of a .NET array

前端 未结 4 1209
醉梦人生
醉梦人生 2020-12-02 18:43

What is the memory layout of a .NET array?

Take for instance this array:

Int32[] x = new Int32[10];

I understand that the bulk of t

相关标签:
4条回答
  • 2020-12-02 18:47

    Great question! I wanted to see it for myself, and it seemed a good opportunity to try out CorDbg.exe...

    It seems that for simple integer arrays, the format is:

    ssssllll000011112222....nnnn0000
    

    where s is the sync block, l the length of the array, and then the individual elements. It seems that there is a finally 0 at the end, I'm not sure why that is.

    For multidimensional arrays:

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

    where s is the sync block, t the total number of elements, l1 the length of the first dimension, l2 the length of the second dimension, then two zeroes?, followed by all the elements sequentially, and finally a zero again.

    Object arrays are treated as the integer array, the contents are references this time. Jagged arrays are object arrays where the references point to other arrays.

    0 讨论(0)
  • 2020-12-02 18:52

    An array object would have to store how many dimensions it has and the length of each dimension. So there is at least one more data element to add to your model

    0 讨论(0)
  • 2020-12-02 19:00

    One way to examine this is to look at the code in WinDbg. So given the code below, let's see how that appears on the heap.

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

    The first thing to do is to locate the instance. As I have made this a local in Main(), it is easy to find the address of the instance.

    From the address we can dump the actual instance, which gives us:

    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
    

    This tells us that it is our Int32 array with 10 elements and a total size of 52 bytes.

    Let's dump the memory where the instance is located.

    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  .m.........@P.=.
    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  .$@.............
    

    I have inserted brackets for the 52 bytes.

    • The first four bytes are the reference to the method table at 01309584.
    • Then four bytes for the Length of the array.
    • Following that are the numbers 0 to 9 (each four bytes).
    • The last four bytes are null. I'm not entirely sure, but I guess that must be where the reference to the syncblock array is stored if the instance is used for locking.

    Edit: Forgot length in first posting.

    The listing is slightly incorrect because as romkyns points out the instance actually begins at the address - 4 and the first field is the Syncblock.

    0 讨论(0)
  • 2020-12-02 19:06

    Great question. I found this article which contains block diagrams for both value types and reference types. Also see this article in which Ritcher states:

    [snip] each array has some additional overhead information associated with it. This information contains the rank of the array (number of dimensions), the lower bounds for each dimension of the array (almost always 0), and the length of each dimension. The overhead also contains the type of each element in the array.

    0 讨论(0)
提交回复
热议问题