Как отобразить управляемые объекты с определенным значением в одном из полей в WinDbg, используя SOS (или SOSEX)?
Моя проблема заключается в следующем:
0:000> !DumpHeap -type Microsoft.Internal.ReadLock -stat
------------------------------
Heap 0
total 0 objects
------------------------------
Heap 1
total 0 objects
------------------------------
Heap 2
total 0 objects
------------------------------
Heap 3
total 0 objects
------------------------------
total 0 objects
Statistics:
MT Count TotalSize Class Name
000007fef3d14088 74247 2375904 Microsoft.Internal.ReadLock
Total 74247 objects
То, как я читаю этот вывод, у меня есть 74,247 Microsoft.Internal.ReadLock
экземпляров в моей куче. Тем не менее, некоторые из них, вероятно, ожидают сбора.
Я хочу отображать только те, которые не ожидают сбора.
Например, 0000000080f88e90
это адрес одного из этих объектов, и это мусор. Я знаю это, потому что:
0:000> !mroot 0000000080f88e90
No root paths were found.
0:000> !refs 0000000080f88e90 -target
Objects referencing 0000000080f88e90 (Microsoft.Internal.ReadLock):
NONE
0:000> !do 0000000080f88e90
Name: Microsoft.Internal.ReadLock
MethodTable: 000007fef3d14088
EEClass: 000007fef3c63410
Size: 32(0x20) bytes
File: C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.ComponentModel.Composition\v4.0_4.0.0.0__b77a5c561934e089\System.ComponentModel.Composition.dll
Fields:
MT Field Offset Type VT Attr Value Name
000007fef3d13fb0 400001e 8 ...oft.Internal.Lock 0 instance 0000000080001010 _lock
000007fef0a8c7d8 400001f 10 System.Int32 1 instance 1 _isDisposed
Как видно, оба sosex.mroot
а также sosex.refs
указать, что никто не ссылается на него, плюс сброс его полей показывает, что он был удален через IDisposable
, поэтому имеет смысл, что объект является мусором (я знаю, что удаление не означает, что объект является мусором, но это в этом случае).
Теперь я хочу отобразить все те экземпляры, которые не являются мусором. Я думаю, что я должен использовать .foreach
команда. Что-то вроде этого:
.foreach(entry {!dumpheap -type Microsoft.Internal.ReadLock -short}){.if (???) {.printf "%p\n", entry} }
Моя проблема в том, что я понятия не имею, что входит в .if
состояние.
Я могу проверить поле _isDisposed следующим образом:
0:000> dd 0000000080f88e90+10 L1
00000000`80f88ea0 00000001
Но .if
ожидает выражения, и все, что у меня есть, это вывод команды. Если бы я знал, как извлечь информацию из вывода команды и упорядочить ее как выражение, я мог бы использовать ее как .if
состояние и будь хорошим.
Итак, мой вопрос заключается в следующем - есть ли способ получить значение поля в качестве выражения, подходящего для .if
? В качестве альтернативы, можно ли проанализировать вывод команды способом, подходящим для использования результата в качестве .if
состояние?
1 ответ
У меня не было примера, который использует объекты ReadLock, но я попытался с помощью Strings, и это мой результат:
.foreach (entry {!dumpheap -short -type Microsoft.Internal.ReadLock})
{
.if (poi(${entry}+10) == 1)
{
.printf "%p\n", ${entry}
}
}
Я использую poi() для получения данных о размере указателя с адреса. Также обратите внимание, что я использую ${entry}, а не запись в обоих, poi() и.printf. Вам также может понравиться! Do ${entry} внутри.if.
В одну строку для копирования / вставки:
.foreach (entry {!dumpheap -short -type Microsoft.Internal.ReadLock}) {.if (poi(${entry}+10) == 1) {.printf "%p\n", ${entry}}}