Reputation: 19031
I created simple jagged array:
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;
}
After that I started debugging my application and looked to this array sturcture in memory (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]
I understand almost all the data: SyncBlockIndexes, TypeHandles, Lengths, Elements. But I can't understand only one line:
0x03022484 0x617A4C8A // ???
What it is?
Update 1:
I tried resolve this address value with different SOS command:
!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>
Update 2:
In array of references types this DWORD should mean address of array element MethodTable. For example, for object[10]
this DWORD is address of MethodTable for System.Object
. But in the case of int[][]
this DWORD is not valid MethodTable address (I use SOS-command DumpMT for checking it).
Upvotes: 4
Views: 267
Reputation: 171206
Quoting from the SSCLI source code (\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]
The extra word you are seeing should be the TypeHandle elementType
:
Only present if the method table is shared among many types (arrays of pointers)
\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[][]
is array of int[]
, TypeHandle of int[]
is TypeDesc. So, strange data is TypeHandle, but it can't resolved by !DumpMT because it's not a MethodTable.
The SSCLI is of course not the real Microsoft CLR implementation, but I understand it is a stripped down version of the 2.0 CLR.
Upvotes: 2