получить трассировку стека при возникновении исключения - PullRequest
4 голосов
/ 15 января 2009

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

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

Кто-нибудь знает простой способ получить трассировку стека после создания исключения? Я думал о простом написании отладочных сообщений, но это будет огромно :-) Я думаю, что есть гораздо лучшие методы, чем этот ...

Я использую Visual Studio 2008 - родной проект C ++ ....

Ответы [ 7 ]

5 голосов
/ 15 января 2009

Если я не очень сильно ошибаюсь, вам нужно знать, какой поток вызвал исключение, чтобы использовать представление стека вызовов отладчика Visual Studio, что, очевидно, является ситуацией catch-22, в которой вы сейчас находитесь.

Одна вещь, которую я бы попробовал, это посмотреть, можно ли отладчику выйти из строя при возникновении исключения (используя Debug> Exceptions). Вам придется явно включить это, но если вы знаете, какой тип исключения генерируется, это может позволить вам определить, где оно генерируется.

Кроме этого, установка точки останова в конструкторе исключения (если оно ваше) также позволит вам определить, откуда оно вызывается.

Если эти методы не работают для вас, я бы посмотрел на сообщения отладки, как вы уже предлагали.

2 голосов
/ 15 января 2009

Это легко сделать с WinDBG , который бесплатен от Microsoft. Вам также нужно установить символы для вашей версии Windows , если у вас их еще нет.

Просто настройте WinDBG в качестве инструмента Crash Dump. Я использую этот параметр реестра: ( Вы можете редактировать пути )

Образец: CrashDumpSettings.reg:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug]
"Auto"="1"
"Debugger"="C:\\progra~1\\debugg~1\\cdb.exe -p %ld -e %ld -g -y SRV*c:\\mss*http://msdl.microsoft.com/download/symbols -c \"$<c:\\Dumps\\CrashDump.cdbscript\""

Вот как может выглядеть ваш CrashDump.cdbscript: ( Это в основном то, что я использую ... Отредактируйте пути соответствующим образом. )

Образец: CrashDump.cdbscript:

.sympath+ c:\windows\symbols;c:\some\path\to\symbols\for\your\project

as /c CrashFirstModule .printf "%mu", @@c++((*(ntdll!_LDR_DATA_TABLE_ENTRY**)&@$peb->Ldr->InLoadOrderModuleList.Flink)->BaseDllName.Buffer) 

.logopen /t c:\dumps\${CrashFirstModule}_process.log
.kframes 100
!analyze -v
~*kv
lmv
.logclose

.dump /mhi /u /b c:\dumps\${CrashFirstModule}_mini.cab
.dump /mhia /u /b c:\dumps\${CrashFirstModule}_full.cab

q

И вы получите хороший файл журнала и несколько дампов, которые вы можете использовать для просмотра состояния процесса, когда исключение произошло с WinDBG. В файле журнала будет проанализирована произошедшая ошибка, включая строку кода, которая вызвала ошибку. Он также перечислит стек вызовов для каждого потока. В листинге стека вызовов поток с # рядом с номером является причиной возникновения исключения. В этих файлах содержится тонна информации. Я рекомендую выбрать приложений отладки для Microsoft .Net и Microsoft Windows от Джона Роббинса. Это отличная книга по отладке, даже если она вышла несколько лет назад. Вы можете получить его от Amazon примерно за 20 долларов.

1 голос
/ 15 января 2009

Вы можете поставить точку останова в конструкторе исключений (т.е. объект, который вы собираетесь выбросить).

Это, конечно, предполагает, что у вас есть общая иерархия исключений.

1 голос
/ 15 января 2009

Эта библиотека выглядит так, как будто она отвечает всем требованиям:

http://www.codeproject.com/KB/threads/StackWalker.aspx

Йохен Кальмбах, похоже, проделал очень тщательную работу, чтобы обернуть сложность низкоуровневого интерфейса dbghelp.dll.

0 голосов
/ 15 января 2009

Если вы не можете получить отладчик для отслеживания происходящего ... и не можете распечатать трассировку стека и поток ...

Полагаю, вам придется добавить немного хорошей смазки для локтей и тяжелую работу. Начните с понимания системы. Как только вы поймете систему, попробуйте разделить систему на две половины. Часть, которая работает, и часть, которая не работает. Затем продолжайте пытаться делать это, пока не приступите к проблеме.

Когда вы пройдете достаточно далеко, попробуйте окружить подозрительный код командой try / catch ... надеюсь, вы сможете использовать отладчик, чтобы остановить выполнение и посмотреть, что происходит.

0 голосов
/ 15 января 2009

Можно ли использовать диалоговое окно «Исключения» (пункт меню Debug | Exceptions..., или Ctrl+Alt+E или Ctrl+D E, в зависимости от привязок клавиатуры), чтобы разбить выполняемый код на отладку в момент, когда выбрасывается конкретное исключение

0 голосов
/ 15 января 2009

Само исключение имеет свойство StackTrace ... поэтому вам просто нужно вернуть ToString ().

Но я верю, что ваша проблема больше похожа на то, как поймать случайное исключение. Если это так, то я помещаю весь основной код в try / catch. Я действительно не очень уверен, если исключение будет брошено в другой поток, это техника будет работать.

Вы должны также поймать ApplicationExeption, который не является производным от Exception.

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