我现在正在调试一个利用许多不同线程的程序。有一个异常是不时抛出的。问题是没有办法知道是什么线程导致了这个问题.有没有一种简单的方法可以在抛出异常后获取堆栈跟踪?我想简单地写一个调试消息,但它将是一个巨大的:-)我想有比这更好的技术...我使用Visual Studio 2008 -原生C++项目。
uurv41yg1#
除非我弄错了,否则您需要知道哪个线程触发了异常,以便使用Visual Studio调试器的调用堆栈视图,这显然是您目前所处的第22条军规。我想尝试的一件事是,看看你是否可以让调试器在异常被抛出时中断(使用“异常”>“异常”)。你必须显式地启用这一点,但如果你知道抛出的异常是什么类型,这可能会让你找到它被抛出的位置。除此之外,在异常的构造函数中放置一个断点(如果它是你自己的构造函数)也应该允许你确定它是从哪里触发的。如果这些方法对你不起作用,我会像你已经建议的那样查看调试消息。
ohfgkhjo2#
这在WinDBG上非常简单,它是微软免费提供的。如果你还没有安装Windows版本的符号,你也需要安装它们。简单地设置WinDBG作为您的崩溃转储工具。我使用此注册表设置:(* 您可能希望编辑路径 *)
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\""
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\projectas /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~*kvlmv.logclose.dump /mhi /u /b c:\dumps\${CrashFirstModule}_mini.cab.dump /mhia /u /b c:\dumps\${CrashFirstModule}_full.cabq
.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发生异常时进程的状态。日志文件将分析发生的错误,包括导致错误的代码行。它还将列出每个线程的调用堆栈。在调用堆栈列表中,在它的编号旁边有#的线程是导致异常的线程。这些文件中有大量的信息。我推荐阅读John Robbins的Debugging Applications for Microsoft .Net and Microsoft Windows。这是一本很棒的关于线程的书,即使是几年前的。你可以从亚马逊上花20美元买到。
#
oipij1gg3#
这个图书馆看起来很符合要求:http://www.codeproject.com/KB/threads/StackWalker.aspxJochen Kalmbach看起来已经完成了非常彻底的工作, Package 了底层dbghelp.dll接口的复杂性。
fv2wmkja4#
你可以在异常构造函数中放置一个断点(即你将要抛出的对象)。当然,这是假设你有一个通用的异常层次结构。
kx5bkwkv5#
如果你不能让调试器捕捉到正在发生的事情......你不能打印堆栈跟踪和线程......我的猜测是,你将不得不投入一些好的体力和努力工作。从理解系统开始。一旦你理解了系统,试着把系统分成两半。工作的部分和不工作的部分。然后继续尝试,直到你深入到问题。当你深入到足够的时候,尝试用try/catch包围可疑的代码......希望你可以使用调试器停止执行,看看发生了什么。
gupuwyp26#
您可以使用“设置”对话框(Debug| Exceptions...菜单项,或Ctrl + Alt + E或Ctrl + D,E,这取决于您的键盘绑定),以便在引发特定异常时将正在运行的代码中断为调试。
Debug
Exceptions...
hmtdttj47#
异常本身具有StackTrace属性.所以你只需要返回ToString()。但我相信你的问题更像是如何捕捉一个随机异常。如果是这样,我所做的就是把所有的主要代码放在一个try/catch中。我真的不太确定如果异常在其他线程中抛出,它这种技术将工作。您还应该捕获不是从Exception派生的ApplicationExeption。
7条答案
按热度按时间uurv41yg1#
除非我弄错了,否则您需要知道哪个线程触发了异常,以便使用Visual Studio调试器的调用堆栈视图,这显然是您目前所处的第22条军规。
我想尝试的一件事是,看看你是否可以让调试器在异常被抛出时中断(使用“异常”>“异常”)。你必须显式地启用这一点,但如果你知道抛出的异常是什么类型,这可能会让你找到它被抛出的位置。
除此之外,在异常的构造函数中放置一个断点(如果它是你自己的构造函数)也应该允许你确定它是从哪里触发的。
如果这些方法对你不起作用,我会像你已经建议的那样查看调试消息。
ohfgkhjo2#
这在WinDBG上非常简单,它是微软免费提供的。如果你还没有安装Windows版本的符号,你也需要安装它们。
简单地设置WinDBG作为您的崩溃转储工具。我使用此注册表设置:(* 您可能希望编辑路径 *)
示例:
CrashDumpSettings.reg
:下面是您的
CrashDump.cdbscript
可能的样子:(* 这基本上是我使用的......适当地编辑路径。*)示例:
CrashDump.cdbscript
:你会得到一个很好的日志文件和一些转储文件,你可以用来查看WinDBG发生异常时进程的状态。日志文件将分析发生的错误,包括导致错误的代码行。它还将列出每个线程的调用堆栈。在调用堆栈列表中,在它的编号旁边有
#
的线程是导致异常的线程。这些文件中有大量的信息。我推荐阅读John Robbins的Debugging Applications for Microsoft .Net and Microsoft Windows。这是一本很棒的关于线程的书,即使是几年前的。你可以从亚马逊上花20美元买到。oipij1gg3#
这个图书馆看起来很符合要求:
http://www.codeproject.com/KB/threads/StackWalker.aspx
Jochen Kalmbach看起来已经完成了非常彻底的工作, Package 了底层dbghelp.dll接口的复杂性。
fv2wmkja4#
你可以在异常构造函数中放置一个断点(即你将要抛出的对象)。
当然,这是假设你有一个通用的异常层次结构。
kx5bkwkv5#
如果你不能让调试器捕捉到正在发生的事情......你不能打印堆栈跟踪和线程......
我的猜测是,你将不得不投入一些好的体力和努力工作。从理解系统开始。一旦你理解了系统,试着把系统分成两半。工作的部分和不工作的部分。然后继续尝试,直到你深入到问题。
当你深入到足够的时候,尝试用try/catch包围可疑的代码......希望你可以使用调试器停止执行,看看发生了什么。
gupuwyp26#
您可以使用“设置”对话框(
Debug
|Exceptions...
菜单项,或Ctrl + Alt + E或Ctrl + D,E,这取决于您的键盘绑定),以便在引发特定异常时将正在运行的代码中断为调试。hmtdttj47#
异常本身具有StackTrace属性.所以你只需要返回ToString()。
但我相信你的问题更像是如何捕捉一个随机异常。如果是这样,我所做的就是把所有的主要代码放在一个try/catch中。我真的不太确定如果异常在其他线程中抛出,它这种技术将工作。
您还应该捕获不是从Exception派生的ApplicationExeption。