Запуск команды из цикла

Я хотел бы запустить команду! Refs для каждого адреса из следующей команды

!dumpgen 2 -type System.DateTime[]

Как это можно сделать. Я знаю, что цикл можно создать следующим образом.

.foreach (myvar {!dumpgen 2 -type System.DateTime[]}) 

Но как я могу получить доступ к адресу объекта, который можно использовать в цикле с! Refs?

1 ответ

Решение

!dumpgen не имеет -short аргумент как !dumpheap Я хотел бы увидеть более простой ответ, чем этот.

Подход 1: сбросить поколение вручную

  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
    
  2. Используйте адреса, чтобы ограничить вывод желаемым поколением:

    !dumpheap -type X <start> <end>
    
  3. Использовать -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: принять решение о создании каждого отдельного объекта

Другое уродливое решение заключается в

  1. Сбросить все адреса объектов (!dumpheap -short а также -type или же -mt)
  2. Запросите генерацию каждого объекта через !gcgen
  3. В зависимости от поколения выполните команду

Вот как это сделать (отформатировано для удобства чтения, поместите все в одну строку):

.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,

Недостаток: может быть медленным, так как работает на всех объектах.

Другие вопросы по тегам