Запуск команды из цикла
Я хотел бы запустить команду! Refs для каждого адреса из следующей команды
!dumpgen 2 -type System.DateTime[]
Как это можно сделать. Я знаю, что цикл можно создать следующим образом.
.foreach (myvar {!dumpgen 2 -type System.DateTime[]})
Но как я могу получить доступ к адресу объекта, который можно использовать в цикле с! Refs?
1 ответ
!dumpgen
не имеет -short
аргумент как !dumpheap
Я хотел бы увидеть более простой ответ, чем этот.
Подход 1: сбросить поколение вручную
Получить адреса кучи
0:003> !eeheap -gc Number of GC Heaps: 1 generation 0 starts at 0x026f1018 generation 1 starts at 0x026f100c generation 2 starts at 0x026f1000
Используйте адреса, чтобы ограничить вывод желаемым поколением:
!dumpheap -type X <start> <end>
Использовать
-short
параметр на!dumpheap
, который выводит только адрес. Этот адрес объекта может затем обрабатываться другими командами.
Также обратите внимание: используя -type
может привести и к другим типам. Лучше использовать таблицу методов с -mt
поскольку только это гарантирует уникальность типов. использование !name2ee
если вы не получите это из другого места.
Полная сессия может выглядеть так:
0:003> !dumpheap -stat
total 345 objects
Statistics:
MT Count TotalSize Class Name
53ab421c 1 12 System.Text.DecoderExceptionFallback
[...]
53ab0d48 135 6640 System.String
53a84518 26 9452 System.Object[]
Total 345 objects
0:003> !eeheap -gc
Number of GC Heaps: 1
generation 0 starts at 0x026f1018
generation 1 starts at 0x026f100c
generation 2 starts at 0x026f1000
[...]
0:003> !name2ee *!System.String
Module: 53841000 (mscorlib.dll)
Token: 0x02000024
MethodTable: 53ab0d48
[...]
0:003> !dumpheap -short -mt 53ab0d48 0x026f1000 0x026f100c
(Хорошо, все мои строки, кажется, в поколении 0, черт возьми:-)
0:003> .foreach (addr {!dumpheap -short -mt 53ab0d48 0x026f1018}) {!refs ${addr}}
Недостаток: вам нужно сделать это для всех куч GC отдельно. Их может быть несколько.
Подход 2: принять решение о создании каждого отдельного объекта
Другое уродливое решение заключается в
- Сбросить все адреса объектов (
!dumpheap -short
а также-type
или же-mt
) - Запросите генерацию каждого объекта через
!gcgen
- В зависимости от поколения выполните команду
Вот как это сделать (отформатировано для удобства чтения, поместите все в одну строку):
.foreach (addr {!dumpheap -short -mt 53ab0d48}) {
.foreach /pS 1 (gen {!gcgen ${addr}}) {
.if ($scmp("${gen}","2")==0) {
!refs ${addr}
}
}
}
где 53ab0d48
таблица методов того типа, который вы ищете, и "2"
это поколение, которое вы хотите. /pS 1
пропускает слово "Gen" в выводе !gcgen
,
Недостаток: может быть медленным, так как работает на всех объектах.