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.