Почему я не могу исследовать файл дампа с помощью команды Windbg !DumpHeap -stat?

Во-первых, я новичок в разных платформах .NET.

Я пытаюсь исследовать дамп управляемого приложения .Net (я не знаю версию), используя Windbg.

Для этого я хочу запустить команду !DumpHeap -stat.
Во-первых, это не работает, потому что sos не загружается:

0:000> !DumpHeap -stat
No export DumpHeap found
0:000> .load sos

Однако, похоже, есть еще одна проблема:

0:000> !DumpHeap -stat
The garbage collector data structures are not in a valid state for traversal.
It is either in the "plan phase," where objects are being moved around, or
we are at the initialization or shutdown of the gc heap. Commands related to 
displaying, finding or traversing objects as well as gc heap segments may not 
work properly. !dumpheap and !verifyheap may incorrectly complain of heap 
consistency errors.
Object <exec cmd="!ListNearObj /d b331dbb0">b331dbb0</exec> has an invalid method table.

В Интернете я нашел несколько сообщений, в которых упоминалось, что эта проблема может быть вызвана несоответствием версий, что подтверждается результатом .chain:

0:000> .chain
Extension DLL search Path:
    => Hereby my entire %PATH% environment variable
Extension DLL chain:
    C:\ProgramData\dbg\sym\SOS_x86_x86_4.7.2563.00.dll\5A334E146eb000\SOS_x86_x86_4.7.2563.00.dll: image 4.7.2563.0, API 1.0.0, built Fri Dec 15 05:16:06 2017
        [path: C:\ProgramData\dbg\sym\SOS_x86_x86_4.7.2563.00.dll\5A334E146eb000\SOS_x86_x86_4.7.2563.00.dll]
    sos: image 4.6.1087.0, API 1.0.0, built Wed Nov 30 05:49:55 2016
        [path: C:\Program Files (x86)\Windows Kits\10\Debuggers\x86\sos.dll]

Как видите, действительно существует несоответствие версий:

C:\...\SOS (ALL CAPS) seems to be of version 4.7.2653
sos (small letters)   seems to be of version 4.6.1087

Давайте решим это:

0:000> .unload C:\ProgramData\dbg\sym\SOS_x86_x86_4.7.2563.00.dll\5A334E146eb000\SOS_x86_x86_4.7.2563.00.dll
0:000> .load C:\ProgramData\dbg\sym\SOS_x86_x86_4.6.1087.00.dll\583E5B8E6b1000\SOS_x86_x86_4.6.1087.00.dll
// I found this file, somewhere on my PC, I just hope it's correct :-)

Это решает проблему? Вроде нет:

0:000> !DumpHeap -stat
The garbage collector data structures are not in a valid state for traversal.
It is either in the "plan phase," where objects are being moved around, or
we are at the initialization or shutdown of the gc heap. Commands related to 
displaying, finding or traversing objects as well as gc heap segments may not 
work properly. !dumpheap and !verifyheap may incorrectly complain of heap 
consistency errors.
Object <exec cmd="!ListNearObj /d b331dbb0">b331dbb0</exec> has an invalid method table.

В порядке. Так что до сих пор нет решения. Может быть, есть и другие версии, которые неверны?

0:000> .cordll
CLR DLL status: Loaded DLL C:\ProgramData\dbg\sym\mscordacwks_x86_x86_4.7.2563.00.dll\5A334E146eb000\mscordacwks_x86_x86_4.7.2563.00.dll

Действительно, CLR, похоже, также ссылается на эту неправильную версию. Давайте решим это:

0:000> .cordll -u
CLR DLL status: No load attempts

(Сначала выгрузите текущий, затем загрузите новый)

0:000> .cordll -lp C:\ProgramData\dbg\sym\mscordacwks_x86_x86_4.6.1087.00.dll\583E5B8E6b1000\mscordacwks_x86_x86_4.6.1087.00.dll
// Again a file I found somewhere on my PC, but it seems not to be working:
CLRDLL: Consider using ".cordll -lp <path>" command to specify .NET runtime directory.
CLR DLL status: ERROR: Unable to load DLL C:\ProgramData\dbg\sym\mscordacwks_x86_x86_4.6.1087.00.dll\583E5B8E6b1000\mscordacwks_x86_x86_4.6.1087.00.dll\mscordacwks_x86_x86_4.7.2563.00.dll, Win32 error 0n87

И теперь у меня нет вариантов: пока я гуглил Win32 error 0n87, я нашел информацию о неправильных параметрах, исследованиях дампа, которые идут неправильно, но не способ загрузить эту CLR DLL.

Может ли кто-нибудь помочь мне здесь (может быть, мы можем начать с определения, какую версию мне нужно выбрать, я просто выбрал случайным образом :-))?
Заранее спасибо


person Dominique    schedule 12.07.2018    source источник
comment
Минидамп для процесса .NET не может быть мини. Он должен включать всю кучу GC. Поговорите с заказчиком, спросите, как они его создали. И имейте в виду, что вы получили этот мини-дамп из-за неправильного поведения программы. Программа, имеющая проблемы с повреждением памяти, действительно склонна падать прямо в тот момент, когда происходит сборка мусора. Вы должны иметь некоторое представление о том, что вам нужно искать, чтобы избежать проблемы с иголкой в ​​стоге сена. Это большой стек.   -  person Hans Passant    schedule 12.07.2018
comment
@HansPassant: если полная информация о куче отсутствует, SOS выводит предупреждение при загрузке расширения.   -  person Thomas Weller    schedule 13.07.2018


Ответы (1)


0:000> .загрузить sos

Эта команда загрузит расширение SOS из каталога плагинов WinDbg. Обычно это версия для .NET 1.x, которая в то время не поставлялась вместе с установкой .NET framework.

Более новые версии .NET Framework поставляются с подходящей версией SOS DLL. Он установлен в каталоге .NET framework, а не в каталоге WinDbg.

Позже мы видим, что вышеуказанная команда загрузила версию 4.6.1087.0. Я не могу этого объяснить, за исключением того, что файл был заменен вручную.

Структуры данных сборщика мусора находятся в недопустимом состоянии для обхода.

Если Интернет говорит, что это может быть несоответствием версии, это может быть правдой — я не могу об этом судить.

Другой вариант заключается в том, что утверждение просто истинно, и в настоящее время выполняется сборка мусора, и, следовательно, куча несовместима.

Третий вариант связан с собственным кодом (C++ или подобным), который записал в память .NET и уничтожил некоторую информацию кучи.

[...] что, похоже, подтверждается результатом .chain:

Итак, мы видим загруженными 2 версии SOS. Очевидно, что один уже был загружен (например, !analyze, вы запускали его раньше?), другой был загружен командой .load sos.

Давайте решим это: [...]

Вы пытаетесь решить проблему, используя .unload и .load. Однако это выгрузит только одну SOS DLL, а затем снова загрузит вторую. Если вам нужна единая чистая версия SOS, вы должны были выполнить .unloaded 2 раза (все библиотеки DLL SOS), а затем загрузить правильную версию.

Это решает проблему? Кажется, нет

Как было сказано ранее, GC может работать прямо сейчас. Вас может заинтересовать связанный вопрос: Как получить дамп памяти процесса .NET, когда .NET не находится в процессе сборки мусора (GC)

Глядя на собственные стеки вызовов (~*k), можно выяснить, выполняет ли .NET в настоящее время сборку мусора.

Может быть, есть и другие версии, которые неверны?

Действительно, CLR, похоже, также ссылается на эту неправильную версию.

Ну так вы так и не определили (или по крайней мере нам не сказали) версию .NET которая загружается в процесс. Выполнение lm vm clr должно дать вам версию, которая загружена (исключением являются длительно работающие процессы, и в это время было установлено обновление, тогда информация о версии может быть неправильной, поскольку она считывается с диска во время захвата аварийного дампа).

Обычная команда для загрузки соответствующей SOS — .loadby sos clr, которая указывает WinDbg загрузить SOS точно из того же места, где находится clr.dll. Это сработает, если аварийный дамп взят с вашей машины. Это может быть сложнее, если вы получили аварийный дамп от кого-то другого.

.cordll -lp C:\ProgramData\dbg\sym\mscordacwks_x86_x86_4.6.1087.00.dll\583E5B8E6b1000\mscordacwks_x86_x86_4.6.1087.00.dll

-lp означает загрузить из пути, но вы указали имя файла. Если вы посмотрите на сообщение об ошибке, оно дважды говорит mscordacwks_x86_x86_4.6.1087.00.dll.

Впрочем, сомневаюсь, что исправление mscordacwks поможет - ни разу не жаловался, что не так. Сообщение об ошибке будет выглядеть так:

CLRDLL: [...]\mscordacwks.dll:<loaded version> doesn't match desired version <expected version>

Сводка

  1. Если вам нужна только одна версия SOS, выгрузите все другие версии.
  2. Если куча находится в недопустимом состоянии, это может быть именно так, а не несоответствие версии. Другой вариант — повреждение кучи некоторым собственным кодом, написанным в куче .NET.
  3. Захват аварийного дампа, когда сборка мусора не выполняется
  4. Дайте нам больше информации о версии CLR, собственных стеках вызовов и т. д., чтобы мы могли лучше вам помочь (проведите небольшое исследование, прежде чем публиковать новые вопросы).
person Thomas Weller    schedule 12.07.2018
comment
спасибо за развернутый ответ. Я смотрю на ваши выводы, но что касается общего вопроса: кажется, что процесс может быть в середине сборки мусора, что может означать, что дамп был сделан не вовремя (но тогда какое подходящее время? :-) ). С другой стороны, я инженер службы поддержки третьей линии, так что это не я делаю дампы: есть инженер службы поддержки первой линии, который отвечает за это, он делает дампы в системе клиента, и, очевидно, клиент хочет знать и иметь объяснение всего, что делается в их системе. - person Dominique; 13.07.2018