Как отобразить управляемые объекты с определенным значением в одном из полей в 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}}}
Другие вопросы по тегам