Как просмотреть локальные переменные в стеке оценки при отладке приложения .NET CLR? - PullRequest
5 голосов
/ 07 февраля 2009

Я использую Windbg (с расширением sos) и пытаюсь отлаживать сбойное приложение. Мне удалось вывести IL из вызова, вызвавшего исключение, и, изучив код, кажется, что я мог бы получить необходимую информацию, если бы мог сбросить содержимое стека оценки. Можно ли что-то сделать с WinDbg & sos?

Вот что я сделал:

  1. Запущен WinDbg
  2. Прилагается к аварийному процессу
  3. loadby sos mscorwks (для загрузки расширения sos)
  4. ! Token2ee theModuleName 0600009a (где theModuleName - это имя приложения (и сборки) t Если я отлаживаю, а 9a - это смещение метода сбоя метода, о котором сообщает инструмент отчетов об ошибках Windows . Я получил этот вывод:

    Модуль: 000e2c3c (theApplicationName.exe)
    Токен: 0x0600009a
    MethodDesc: 000e67c8
    Имя: MyNamespace.MyClassName.theCulpritFn (MyOtherClass)
    JITTED код адрес: 0081b1d0

  5. ! Dumpil 00e67c8 (который сбросил IL для рассматриваемого метода) . Это вывод:

    
    // ..
    // .. the previous code omitted for brevity
    .catch
    {
     IL_0071: stloc.0
     IL_0072: nop
     IL_0073: ldstr "Can't set CurrentServer property for: "
     IL_0078: ldarg.0
     IL_0079: ldfld MyNamespace.MyClassName::_currentServer
     IL_007e: brtrue.s IL_0087
     IL_0080: ldstr ""
     IL_0085: br.s IL_0092
     IL_0087: ldarg.0
     IL_0088: ldfld MyNamespace.MyClassName::_currentServer
     IL_008d: callvirt MyNamespace.MyOtherClass::get_Name
     IL_0092: call System.String::Concat
     IL_0097: ldloc.0
     IL_0098: newobj MyNamespace.MySpecialExceptionType::ctor
     IL_009d: throw
    } 
    

    Вопрос в том, есть ли способ увидеть, что было помещено в стек до того, как было сгенерировано исключение. Если я не ошибаюсь, аргумент, передаваемый в конструктор исключений, должен быть локальной переменной с индексом 0 в стеке оценки.

    P.S. Когда я попытался позвонить ! Clrstack -a , я получил сообщение: Невозможно пройти управляемый стек. Текущий поток, скорее всего, не является управляемым потоком. Вы можете запустить! Threads, чтобы получить список управляемых потоков в процессе.

Спасибо!

Ответы [ 2 ]

5 голосов
/ 07 февраля 2009

Вам необходимо идентифицировать и выбрать правильную ветку. Идентификатор текущего потока отображается в приглашении WinDbg.

!threads отобразит все управляемые темы в вашем приложении. После идентификации вы можете переключать потоки, используя ~Xs, где X - идентификатор WinDbg для потока.

!clrstack покажет вам трассировку стека. Если вам нужны локальные параметры и / или параметры, используйте -l / -p (или -a для обоих).

Вы можете просмотреть все потоки и перечислить их стек вызовов с помощью ~*e!clrstack.

Если local / parameters не дает вам того, что вам нужно, используйте !dso для отображения объектов, помещенных в стек.

2 голосов
/ 22 февраля 2009

Ух ты, это трудно без реальной дампы, через которую тыкаешь. :-)

Вот пара вопросов ... и затем я добавлю одну команду, которая ранее не была указана в ответах выше.

Вопросы:

  1. Вы уверены, что поймали первое исключение, а не только последнее, которое было обработано и сорвано в процессе?

  2. Можете ли вы взглянуть на собственный стек вызовов для потока, выдавшего исключение.
    Примечание: должен быть вызов RaiseException () или нарушение прав доступа.

  3. Остерегайтесь асинхронных исключений, которые не имеют абсолютно никакого отношения к вашему коду и могут войти и загнать вас в блок перехвата ... или еще хуже (Thread.AbortException / System.OutofMemoryException и ... StackOverflowException: - )

Чтобы продолжить, вы запускаете ! Dumpstack в неисправном потоке. Вывод не точен , однако он делает потрясающую работу по обходу стека вызовов потоков, и вы можете повезет, и вы увидите в сообщении символ @ , который ссылается на исключение с .cxr и .exr. Если вы это сделаете, то можете запустить .cxr -cxr-address и посмотреть, какое первое исключение было в цепочке исключений.

Точка: Хотя я могу быть сторонним в вопросе, если исключение вызвало WER, оно было не обработано и остановило процесс. Возможно, вы захотите зарегистрировать начальный стек вызовов или добавить предыдущее исключение как внутреннее исключение, чтобы Вы можете определить основную причину.

Спасибо, Аарон

...