.NET中锯齿状数组的内部结构

时间:2013-09-12 20:50:41

标签: .net arrays memory clr jagged-arrays

我创建了简单的锯齿状数组:

int[][] a = new int[2][];
for (int i = 0; i < 2; i++)
{
    a[i] = new int[3];
    for (int j = 0; j < 3; j++)
        a[i][j] = i * 3 + j;
}

之后我开始调试我的应用程序并查看内存中的这个数组结构(x86):

0x03022478           0  // SyncBlockIndex (a)
0x0302247C  0x61B8D5BC  // TypeHandle (a)
0x03022480           2  // a.Length
0x03022484  0x617A4C8A  // ???
0x03022488  0x03022494  // a[0]
0x0302248C  0x030224AC  // a[1]
0x03022490           0  // SyncBlockIndex (a[0])
0x03022494  0x61B9C448  // TypeHandle (a[0])
0x03022498           3  // a[0].Length
0x0302249C           0  // a[0][0]
0x030224A0           1  // a[0][1]
0x030224A4           2  // a[0][2]
0x030224A8           0  // SyncBlockIndex (a[1])
0x030224AC  0x61B9C448  // TypeHandle (a[1])
0x030224B0           3  // a[1].Length
0x030224B4           3  // a[1][0]
0x030224B8           4  // a[1][1]
0x030224BC           5  // a[1][2]

我理解几乎所有数据:SyncBlockIndexes,TypeHandles,Lengths,Elements。但我只能理解一行:

0x03022484  0x617A4C8A  // ???

它是什么?

更新1:

我尝试使用不同的SOS命令解析此地址值:

!DumpArray 0x617A4C8A
<Note: this object has an invalid CLASS field>
Invalid object

!DumpAssembly 0x617A4C8A
Fail to fill Assembly

!DumpClass 0x617A4C8A
Invalid EEClass address

!DumpDomain 0x617A4C8A
Fail to fill AppDomain

!DumpMD 0x617A4C8A
617a4c8a is not a MethodDesc

!DumpMT 0x617A4C8A  
617a4c8a is not a MethodTable

!DumpObj 0x617A4C8A 
<Note: this object has an invalid CLASS field>
Invalid object    

!DumpSig 0x617A4C8A
!DumpSig <sigaddr> <moduleaddr>

更新2:

在引用类型数组中,此DWORD应表示数组元素MethodTable的地址。例如,对于object[10],此DWORD是System.Object的MethodTable的地址。但是在int[][]的情况下,这个DWORD不是有效的MethodTable地址(我使用SOS命令DumpMT来检查它)。

1 个答案:

答案 0 :(得分:2)

引用SSCLI源代码(\sscli20_20060311\sscli20\clr\src\vm\object.h):

// ArrayBase encapuslates all of these details.  In theory you should never
// have to peek inside this abstraction
class ArrayBase : public Object
{
    ...
    // This MUST be the first field, so that it directly follows Object.  This is because
    // Object::GetSize() looks at m_NumComponents even though it may not be an array (the
    // values is shifted out if not an array, so it's ok). 
    DWORD       m_NumComponents;
    ...
    // What comes after this conceputally is:
    // TypeHandle elementType;        Only present if the method table is shared among many types (arrays of pointers)
    // INT32      bounds[rank];       The bounds are only present for Multidimensional arrays   
    // INT32      lowerBounds[rank];  Valid indexes are lowerBounds[i] <= index[i] < lowerBounds[i] + bounds[i]

您看到的额外字词应为TypeHandle elementType

  

仅在方法表在许多类型(指针数组)之间共享时才出现

\sscli20_20060311\sscli20\clr\src\vm\typehandle.h:

// At the present time a TypeHandle can point at two possible things
//
//      1) A MethodTable    (Intrinsics, Classes, Value Types and their instantiations)
//      2) A TypeDesc       (all other cases: arrays, byrefs, pointer types, function pointers, generic type variables) 

int[][]int[]的数组,int[]的TypeHandle是TypeDesc。所以,奇怪的数据是TypeHandle,但它无法通过!DumpMT解决,因为它不是MethodTable。

SSCLI当然不是真正的Microsoft CLR实现,但我知道它是2.0 CLR的精简版本。