【问题标题】:get stack trace when exception is thrown抛出异常时获取堆栈跟踪
【发布时间】:2009-01-15 12:34:49
【问题描述】:

我现在正在调试一个使用许多不同线程的程序。

有一个不时抛出的异常。问题是没有办法知道是什么线程导致了问题...

有谁知道抛出异常后获取堆栈跟踪的简单方法?我想过简单地编写一个调试消息,但这将是一个巨大的:-) 我想有比这个更好的技术......

我正在使用 Visual Studio 2008 - 本机 C++ 项目....

【问题讨论】:

    标签: c++ visual-studio-2008 debugging


    【解决方案1】:

    除非我弄错了,否则您需要知道哪个线程触发了异常才能使用 Visual Studio 调试器的调用堆栈视图,这显然是您目前所处的 catch-22 情况。

    我会尝试的一件事是查看在抛出异常时是否可以让调试器中断(使用“调试”>“异常”)。您必须显式启用此功能,但如果您知道抛出什么类型的异常,这可能会让您知道它是在哪里抛出的。

    除此之外,在异常的构造函数中放置一个断点(如果它是您自己的)也应该允许您确定它是从哪里触发的。

    如果这些方法对您不起作用,我会按照您的建议查看调试消息。

    【讨论】:

      【解决方案2】:

      这对于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\""
      

      这就是你的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 发生异常时,您会得到一个不错的日志文件和一些转储,您可以使用这些转储来查看进程的状态。日志文件将对发生的错误进行分析,包括导致错误的代码行。它还将列出每个线程的调用堆栈。在调用堆栈列表中,编号旁边带有# 的线程是导致异常的线程。这些文件中有大量信息。我建议选择 John Robbins 的 Debugging Applications for Microsoft .Net and Microsoft Windows。这是一本关于调试的好书,即使它是几年前的。你可以以大约 20.00 美元的价格从亚马逊购买它。

      【讨论】:

        【解决方案3】:

        这个库看起来很符合要求:

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

        Jochen Kalmbach 看起来在封装低级 dbghelp.dll 接口的复杂性方面做得非常彻底。

        【讨论】:

          【解决方案4】:

          您可以在异常构造函数(即您将要抛出的对象)中放置一个断点。

          这当然假设您有一个共同的异常层次结构。

          【讨论】:

            【解决方案5】:

            您能否使用“异常”对话框(Debug | Exceptions... 菜单项,或Ctrl+Alt+ECtrl+D E,取决于您的键盘绑定)在抛出特定异常时将正在运行的代码中断为调试?

            【讨论】:

              【解决方案6】:

              如果您无法让调试器捕捉正在发生的事情...并且您无法打印堆栈跟踪和线程...

              我的猜测是,您将不得不付出一些努力工作。从了解系统开始。了解系统后,尝试将系统分成两半。有效的部分和无效的部分。然后继续尝试这样做,直到您深入解决问题。

              当您深入研究时,尝试使用 try/catch 包围可疑代码...希望您可以使用调试器停止执行并查看发生了什么。

              【讨论】:

                【解决方案7】:

                异常本身具有 StackTrace... 属性,因此您只需返回 ToString( )。

                但我相信您的问题更像是如何捕获随机异常。如果是这样,我所做的就是将所有主要代码放在 try/catch 中。我真的不确定是否在其他线程中引发了异常,这种技术是否有效。

                您还应该捕获不是从 Exception 派生的 ApplicationExeption。

                【讨论】:

                • ofer 提到他的项目是一个原生 C++ 项目。我可能错了,但您的建议是针对 .NET 的,对吗?
                • 是的...我的错误...以为你在 .NET 中的哪个位置
                猜你喜欢
                • 2010-10-10
                • 2021-10-08
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2012-08-24
                • 1970-01-01
                • 2023-03-22
                • 2011-09-10
                相关资源
                最近更新 更多