【问题标题】:Get stack trace from uncaught exception?从未捕获的异常中获取堆栈跟踪?
【发布时间】:2010-12-20 06:05:55
【问题描述】:

我意识到这将是特定于平台的:有没有办法从未捕获的 C++ 异常中获取堆栈跟踪,但从抛出异常的点开始?

我有一个 Windows 结构化异常处理程序来捕获访问冲突等并生成一个小型转储。但是,由于未捕获的 C++ 异常,当然不会在终止的情况下调用它,因此没有崩溃转储。

我目前正在寻找 Windows 解决方案(无论多么肮脏!),但如果可能的话,我想了解其他平台。

谢谢。

【问题讨论】:

    标签: c++ windows exception stack-trace


    【解决方案1】:

    我们使用来自该站点的信息在上一个标题中为未处理的异常实施了 MiniDumps:

    http://beefchunk.com/documentation/sys-programming/os-win32/debug/www.debuginfo.com/articles/effminidumps.html

    要捕获 windows 上未处理的异常,请查看:

    SetUnhandledExceptionFilter (http://msdn.microsoft.com/en-us/library/ms680634%28VS.85%29.aspx)。

    作为助手,我们花了很多时间试验不同级别的小型转储,直到我们确定了一个。事实证明,这在现实世界的崩溃中没有真正的用处,因为我们不知道在实施小型转储时它们会是什么。它是非常特定于应用程序的,也是特定于崩溃的,所以我的建议是尽早添加 minidump 处理程序,它会随着项目和质量检查而增长,它会在某个时候成为救命稻草(希望在现实世界中出现)也)。

    【讨论】:

    • 这确实适用于未捕获的 C++ 异常(嗯,适用于使用 Visual Studio 构建的应用程序)。我最初的误解是由于某处图书馆深处隐藏的 catch(...) 块......!
    • 一篇好文章!您使用 MiniDumpWriteDump(GetCurrentProcess()...) 但 MSDN 说 MiniDumpWriteDump() 应该从单独的进程或至少从单独的线程调用。您的代码不会导致错误的堆栈跟踪吗?
    • 我们得到的 stracktraces 是正确的,但这是 10 年前的事了,所以我无法验证那是侥幸还是当时功能有不同的要求。让我们知道您的进展情况,我很乐意更新答案以使其更准确。
    【解决方案2】:

    您可以使用try-except Statement 将C++ 异常“转换”为结构化异常(然后您可以从中获得良好的堆栈跟踪)。考虑一下:

    // Your function to get a backtrace from a CONTEXT
    const char *readBacktrace( CONTEXT &ctx );
    
    extern "C"
    static DWORD exceptFilter( struct _EXCEPTION_POINTERS* exInf )
    {
        OutputDebugStringA( readBacktrace( *exInf->ContextRecord ) );
        return EXCEPTION_EXECUTE_HANDLER;
    }
    
    try {
      // your C++ code which might yield exceptions
    } catch ( ... ) {
      // In case a C++ exception occurs, raise a structured exception and catch it    immediately
      // so that we get a CONTEXT object which we can use to generate a stack trace.
      __try {
        RaiseException( 1, 0, 0, NULL );
      } __except( exceptFilter( GetExceptionInformation() ) ) {
      }
    }
    

    这有点笨拙,但好处是您可以将 __try { } __except() { } 部分放入通用dumpStackTrace() 函数中。然后,您可以根据需要从程序中的任何位置产生堆栈跟踪。

    【讨论】:

    • 该代码无法真正编译,因为您不能在 try/catch 中使用 __try/__except。
    【解决方案3】:

    尝试使用 set_terminate 安装终止处理程序。并在其中使用迷你转储功能获取堆栈跟踪。也许它会起作用。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-28
    • 1970-01-01
    • 2023-03-22
    • 2011-06-01
    相关资源
    最近更新 更多