4

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

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 是 MethodTable 的地址System.Object。但是在int[][]这个 DWORD 不是有效的 MethodTable 地址的情况下(我使用 SOS 命令 DumpMT 来检查它)。

4

1 回答 1

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[],TypeHandleint[]是 TypeDesc。所以,奇怪的数据是 TypeHandle,但它不能被 !DumpMT 解析,因为它不是 MethodTable。

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

于 2013-09-12T23:14:00.867 回答