我创建了简单的锯齿状数组:
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来检查它)。
答案 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的精简版本。