Почему SOS/SOSEx неправильно интерпретирует значения System.Collections.Generic.List.Enumerator?
Я написал простое приложение на C#:
static void Main(string[] args)
{
var list = new List<int> {500,400,300,200,100};
var listEnumerator = list.GetEnumerator();
listEnumerator.MoveNext();
} // <--- breakpoint here
Я поставил точку останова в конце, запустил ее с помощью Visual Studio, затем запустил windbg и подключил к процессу (с включенным флажком "неинвазивный").
Затем я ввел эти команды:
.load C:\Program Files (x86)\Windows Kits\8.0\Debuggers\x86\sosex.dll
!mframe 17
!mdt listEnumerator
Вывод, который я получил, был явно неправильным (все поля перепутаны, кажется, что он сообщает значение 'index' в 'current', значение 'current' в 'version' и значение version 'в' index ' '. Он получил только одно поле - первое.
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)
Затем я попытался использовать SOS!DumpVC, и получил ту же путаницу:
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
Почему это происходит?
1 ответ
Проблема в том, что CLR переупорядочил поля структуры перечислителя для закрытого типа (перечислитель типа int), чтобы они не соответствовали открытому типу (перечислитель типа T). Sosex использовал открытый тип для чтения полей вместо закрытого типа. Эта ошибка в sosex теперь исправлена.