debugging 在引发异常时获取堆栈跟踪

cotxawn7  于 2023-10-24  发布在  其他
关注(0)|答案(7)|浏览(160)

我现在正在调试一个利用许多不同线程的程序。
有一个异常是不时抛出的。问题是没有办法知道是什么线程导致了这个问题.
有没有一种简单的方法可以在抛出异常后获取堆栈跟踪?
我想简单地写一个调试消息,但它将是一个巨大的:-)我想有比这更好的技术...
我使用Visual Studio 2008 -原生C++项目。

uurv41yg

uurv41yg1#

除非我弄错了,否则您需要知道哪个线程触发了异常,以便使用Visual Studio调试器的调用堆栈视图,这显然是您目前所处的第22条军规。
我想尝试的一件事是,看看你是否可以让调试器在异常被抛出时中断(使用“异常”>“异常”)。你必须显式地启用这一点,但如果你知道抛出的异常是什么类型,这可能会让你找到它被抛出的位置。
除此之外,在异常的构造函数中放置一个断点(如果它是你自己的构造函数)也应该允许你确定它是从哪里触发的。
如果这些方法对你不起作用,我会像你已经建议的那样查看调试消息。

ohfgkhjo

ohfgkhjo2#

这在WinDBG上非常简单,它是微软免费提供的。如果你还没有安装Windows版本的符号,你也需要安装它们。
简单地设置WinDBG作为您的崩溃转储工具。我使用此注册表设置:(* 您可能希望编辑路径 *)

示例:CrashDumpSettings.reg

  1. Windows Registry Editor Version 5.00
  2. [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug]
  3. "Auto"="1"
  4. "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

  1. .sympath+ c:\windows\symbols;c:\some\path\to\symbols\for\your\project
  2. as /c CrashFirstModule .printf "%mu", @@c++((*(ntdll!_LDR_DATA_TABLE_ENTRY**)&@$peb->Ldr->InLoadOrderModuleList.Flink)->BaseDllName.Buffer)
  3. .logopen /t c:\dumps\${CrashFirstModule}_process.log
  4. .kframes 100
  5. !analyze -v
  6. ~*kv
  7. lmv
  8. .logclose
  9. .dump /mhi /u /b c:\dumps\${CrashFirstModule}_mini.cab
  10. .dump /mhia /u /b c:\dumps\${CrashFirstModule}_full.cab
  11. q

你会得到一个很好的日志文件和一些转储文件,你可以用来查看WinDBG发生异常时进程的状态。日志文件将分析发生的错误,包括导致错误的代码行。它还将列出每个线程的调用堆栈。在调用堆栈列表中,在它的编号旁边有#的线程是导致异常的线程。这些文件中有大量的信息。我推荐阅读John Robbins的Debugging Applications for Microsoft .Net and Microsoft Windows。这是一本很棒的关于线程的书,即使是几年前的。你可以从亚马逊上花20美元买到。

展开查看全部
oipij1gg

oipij1gg3#

这个图书馆看起来很符合要求:
http://www.codeproject.com/KB/threads/StackWalker.aspx
Jochen Kalmbach看起来已经完成了非常彻底的工作, Package 了底层dbghelp.dll接口的复杂性。

fv2wmkja

fv2wmkja4#

你可以在异常构造函数中放置一个断点(即你将要抛出的对象)。
当然,这是假设你有一个通用的异常层次结构。

kx5bkwkv

kx5bkwkv5#

如果你不能让调试器捕捉到正在发生的事情......你不能打印堆栈跟踪和线程......
我的猜测是,你将不得不投入一些好的体力和努力工作。从理解系统开始。一旦你理解了系统,试着把系统分成两半。工作的部分和不工作的部分。然后继续尝试,直到你深入到问题。
当你深入到足够的时候,尝试用try/catch包围可疑的代码......希望你可以使用调试器停止执行,看看发生了什么。

gupuwyp2

gupuwyp26#

您可以使用“设置”对话框(Debug| Exceptions...菜单项,或Ctrl + Alt + E或Ctrl + D,E,这取决于您的键盘绑定),以便在引发特定异常时将正在运行的代码中断为调试。

hmtdttj4

hmtdttj47#

异常本身具有StackTrace属性.所以你只需要返回ToString()。
但我相信你的问题更像是如何捕捉一个随机异常。如果是这样,我所做的就是把所有的主要代码放在一个try/catch中。我真的不太确定如果异常在其他线程中抛出,它这种技术将工作。
您还应该捕获不是从Exception派生的ApplicationExeption。

相关问题