Почему мини-дампы не дают хорошие стеки вызовов? - PullRequest
16 голосов
/ 12 октября 2009

За последние годы я использовал мини-дампы во многих игровых проектах, и у них, похоже, есть 50% -ный шанс иметь действительный стек вызовов. Что я могу сделать, чтобы у них были лучшие стеки вызовов?

Я пытался поместить последнюю версию dbghelp.dll в каталог exe. Это, кажется, помогает некоторым.

Visual Studio 2008 или 2010 лучше? (Я все еще на VS 2005).

Код, который я использую, выглядит как этот образец .

Ответы [ 5 ]

25 голосов
/ 28 октября 2015

Одна вещь, которую вы можете сделать, чтобы повысить точность стеков вызовов, обнаруженных в дампах, - это использовать отладчик, отличный от Visual Studio, в частности, использовать WinDbg или другой инструмент, использующий механизм отладки «Отладчик Windows», найденный в dbgeng.dll. (в отличие от механизма отладки Visual Studio Debugger, который используется в Visual Studio).

По нашему опыту, WinDbg на 100% надежен в создании хороших стеков вызовов из тех же дампов, где Visual Studio создает непригодные или дико неточные стеки вызовов. Из того, что я могу сказать, в случаях, когда необработанное исключение является источником сбоя, WinDbg автоматически выполняет сложный процесс восстановления / восстановления стека вызовов , а Visual Studio - нет (или не может?). Два отладчика используют различную эвристику для интерпретации стеков

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

Руководство простого Mortal по извлечению хороших стеков вызовов

Они упорядочены от «самых быстрых / самых простых» до «самых медленных / самых загадочных для интерпретации».

  1. Самый простой вариант: используйте DbgDiag от Microsoft

    Это малоизвестный инструмент, который автоматизирует большой анализ общих проблем, и его достаточно просто дать непрограммистам или даже клиентам. Это быстрый и почти надежный инструмент, и он стал моим инструментом «быстрого перехода» для быстрого анализа входящего аварийного дампа.

    • Запустить приложение «Анализ отладки»
    • Установите флажок «CrashHangAnalysis» на главной странице
    • Перетащите дамп в панель «Файлы данных» на главной странице
    • Нажмите «Начать анализ»


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

    DebugDiag даже автоматизирует некоторые из более сложных анализов, которые возможны, но болезненны в WinDbg (например, отслеживание того, какой из 350 потоков в вашем приложении отвечает за взаимоблокировку).

    Примечание. Chrome не будет загружать или открывать файлы .mhtml по соображениям безопасности, поэтому для его использования необходимо открыть его в Internet Explorer или Microsoft Edge. Это раздражает, и я подал запрос в команду DebugDiag (dbgdiag@microsoft.com), чтобы изменить формат на обычный HTML

  2. Средний вариант: установить WinDbg в качестве альтернативного механизма отладки для Visual Studio

    • Установите Visual Studio, если он еще не установлен. Это необходимо сделать до следующего шага.
    • Установите Windows Driver Kit (WDK)
    • Запустите Visual Studio и ( эта часть важна! ) используйте новую опцию «Файл -> Открыть -> Сбой дампа ...», чтобы открыть дамп. Это отладит аварийный дамп с помощью отладчика Windows (, если вместо этого перетащить дамп в Visual Studio или использовать стандартную опцию «Файл -> Открыть -> Файл ...», чтобы открыть дамп, будет отлаживать его, используя старый механизм отладки Visual Studio ... поэтому будьте осторожны, используя правильный параметр ).
    • Теперь вы должны иметь возможность видеть правильный стек вызовов и перемещаться с помощью графического интерфейса Visual Studio, хотя некоторые вещи работают по-другому (окна просмотра требуют использования незнакомого синтаксиса WinDbg, идентификаторы потоков отличаются и т. Д.). Примечание: пользовательский интерфейс Visual Studio может быть очень вялым, особенно если задействовано много потоков и открыты окна «потоки» или «параллельные стеки».
  3. Хардкорная опция: используйте WinDbg напрямую

    • Запустить WinDbg.exe
    • Перетащите свой дамп в окно WinDbg
    • Введите !analyze -v и нажмите Enter. Через некоторое время WinDbg выдаст стек вызовов аварийного завершения, а также оценит источник проблемы. Если вы анализируете тупик, вы можете попробовать !analyze -v -hang, и WinDbg будет часто показывать вам цепочку зависимостей.


    На данный момент у вас может быть вся необходимая информация! Однако, если затем вы захотите проверить состояние процесса в отладчике Visual Studio, вы можете предпринять следующие дополнительные шаги:

    • Открыть аварийный дамп в Visual Studio
    • Щелкните правой кнопкой мыши в окне стека вызовов и выберите «Перейти к разборке»
    • Вставьте шестнадцатеричный адрес из верхней строки выходного стека вызовов WinDbg в строку «Адрес» окна «Разборка» и нажмите клавишу ввода. Теперь вы находитесь в месте сбоя и смотрите на разобранный код.
    • Щелкните правой кнопкой мыши в окне разборки и выберите «Перейти к исходному коду», чтобы перейти к исходному коду местоположения. Теперь вы смотрите на исходный код на сайте аварии.

Примечание: все вышеперечисленное требует, чтобы были настроены правильные пути сервера символов, иначе вы не сможете разрешить символы в стеках вызовов. Я рекомендую установить переменную среды _NT_SYMBOL_PATH , чтобы она автоматически была доступна для Visual Studio, WinDbg и DebugDiag.

6 голосов
/ 12 октября 2009

Чего не хватает в вашем стеке вызовов? У вас есть куча адресов, которые не разрешаются в правильные имена функций (например, 0x8732ae00 вместо CFoo: Bar ())? Если это так, то вам нужно поместить свои .PDB туда, где их может найти ваш отладчик, или настроить сервер символов и установить «Пути символов» в контекстном меню правой кнопки панели «Модули». ,

Мы храним каждую .PDB из каждого двоичного файла каждый раз, когда кто-то регистрирует новый список изменений Perforce, так что, когда дамп возвращается от кого-либо внутри офиса или от любого покупателя в рознице, у нас есть .PDB, соответствующая версии Игра, которую они запускали. С установленным сервером символов и путями все, что мне нужно сделать, это просто дважды щелкнуть мышью на .mdmp, и он будет работать каждый раз.

Или у вас есть стек вызовов, который имеет только одну функцию? Мол, 0x8538cf00 без чего-либо еще выше в стеке? Если это так, то ваш сбой на самом деле поврежден сам стек. Если адреса возврата в обратной цепочке были перезаписаны, естественно, отладчик не сможет их разрешить.

Иногда вы также обнаружите, что поток, который на самом деле испускает мини-дамп, не тот, который выдал исключение, вызвавшее сбой. Посмотрите в окне «Потоки», чтобы увидеть, содержит ли один из других потоков код ошибки.

Если вы отлаживаете сборку "Release" - то есть, скомпилированную со всеми включенными флагами оптимизации - вам придется смириться с тем, что у отладчика возникнут проблемы с поиском локальных переменных и некоторых других данных. , Это связано с тем, что включение оптимизаций означает, что компилятор может хранить данные в регистрах, свернуть вычисления и, как правило, делать множество вещей, которые предотвращают фактическую запись данных в стек. Если это ваша проблема, то вам нужно открыть окно разборки и отследить данные вручную, или перестроить двоичный файл отладки и воспроизвести проблему, где вы можете ее посмотреть.

4 голосов
/ 12 октября 2009

Отключите Оптимизацию указателя кадра, если вам нужны дампы стека. Указатели кадров используются для явного определения стек кадров. Без них отладчик должен определять местоположение каждого кадра.

1 голос
/ 03 ноября 2015

Код для записи минидампа вряд ли будет актуален. Основными вещами, которые записывает мини-дамп, являются информация модуля (для получения символов) и полное содержимое всех стеков потоков. Помимо этой базовой информации (которая всегда записывается), ничто другое не имеет значения.

Получение хороших символов (включая файлы PE) имеет решающее значение для обхода стека. Более подробную информацию можно найти здесь: https://randomascii.wordpress.com/2013/03/09/symbols-the-microsoft-way/

Я считаю, что Visual Studio обычно надежно отображает стеки вызовов. Он автоматически отображает соответствующий стек вызовов из записи исключения и упрощает изменение потоков, так что вы можете видеть стеки вызовов всех потоков. Иногда он пытается «скрыть» детали, которые, по его мнению, могут сбить вас с толку - хорошо это или плохо, зависит от вашего уровня квалификации.

Windbg по умолчанию показывает стек вызовов кода, который записал аварийный дамп, а не аварийный стек вызовов. Windbg требует, чтобы вы пошли ".ecxr" или "! Analyse -v", чтобы увидеть стек аварийного отказа. Я нахожу это раздражающим. Windbg также требует больше настроек для того, чтобы быть полезным.

Два отладчика имеют различную эвристику обхода стека. Эта эвристика необходима, например, если вы позвоните или вернетесь к нулевому адресу, так как для этого адреса нет информации о размотке. Для «чистых» сбоев, где ошибочная инструкция находится в обычном коде, эти эвристики менее важны.

Ходьба в стеке почти наверняка улучшилась за последние десять лет. VS 2015 Community Edition очень эффективный и бесплатный, так что вы можете попробовать его.

Если вы используете windbg, то можете попробовать несколько экспериментов:

!vc7fpo - toggles some of the windbg heuristics.
!stackdbg d, 7, f - turns on windbg stack walk
k1 - walks one level of the stack, spitting diagnostics as controlled by !stackdbg
dds esp - dumps the raw contents of the stack, doing a symbol lookup on each pointer

Если вы обновляетесь до VS 2015 и по-прежнему возникают проблемы, вполне вероятно, что сбои обхода стека относятся именно к сбоям, которые вы видите. Если переполнение буфера нарушает стек перед сбоем, то стек вызовов будет безвозвратно поврежден. Ваш вопрос содержит слишком мало информации о том, какие неудачи вы видите, чтобы поставить точный диагноз. Я считаю, что стековые дисплеи обоих отладчиков достаточно надежны, но я также обычно понимаю, почему они иногда терпят неудачу, и когда это происходит, я все равно могу извлечь нужную мне информацию.

0 голосов
/ 12 октября 2009

Я не использую мини-дампы, а скорее сбрасываю стек "вручную" в лог-файл (см. www.ddj.com / cpp / 185300443 и Как регистрировать кадры стека в Windows x64 ).

Я сталкиваюсь с подобным поведением, как и у вас: иногда существует допустимый стек вызовов, иногда его нет. В небольшом числе случаев стек может быть действительно поврежден. Возможно, в 1/3 всех случаев установленный обработчик исключений вообще не вызывается! Я думаю, что это как-то проблема обработки исключений в Windows.

...