I wrote a simple C# app:
static void Main(string[] args)
{
var list = new List<int> {500,400,300,200,100};
var listEnumerator = list.GetEnumerator();
listEnumerator.MoveNext();
} // <--- breakpoint here
I put a breakpoint at the end, ran it with Visual Studio, then fired up windbg and attached to the process (with the "non-invasive" checkbox turned on).
I then entered these commands:
.load C:\Program Files (x86)\Windows Kits\8.0\Debuggers\x86\sosex.dll
!mframe 17
!mdt listEnumerator
The output I got was clearly wrong (the fields are all messed up, it seems to report the value of 'index' under 'current', the value of 'current' under 'version', and the value of version' under 'index'. It got only one field right - the first one.
Local #0: (System.Collections.Generic.List`1+Enumerator) VALTYPE (MT=72dfd838, ADDR=0029efb8)
list:02632464 (System.Collections.Generic.List`1[[System.Int32, mscorlib]])
index:0x5 (System.Int32)
version:0x1f4 (System.Int32)
current:00000001 (T)
I then tried to use SOS's !DumpVC instead, and got the same confusion:
0:000> !DumpVC 72dfd838 0029efb8
Name: System.Collections.Generic.List`1+Enumerator
MethodTable: 72dfd838
EEClass: 72a32d38
Size: 24(0x18) bytes
File: C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
Fields:
MT Field Offset Type VT Attr Value Name
736ae16c 4000c99 0 ...Generic.List`1[T] 0 instance 02632464 list
72e03aa4 4000c9a 8 System.Int32 1 instance 5 index
72e03aa4 4000c9b c System.Int32 1 instance 500 version
00000000 4000c9c 4 VAR 0 instance 00000001 current
Why does this happen?
The problem is that the CLR has re-ordered the fields of the enumerator struct for the closed type (enumerator of int) so that they don't match the open type (enumerator of T). Sosex was using the open type to read the fields instead of the closed type. This bug in sosex has now been fixed.