从未捕获的异常中获取堆栈跟踪?

4
我知道这个问题会因平台而异:有没有办法从抛出异常的点获得未捕获的C++异常的堆栈跟踪?
我有一个Windows结构化异常处理程序来捕获访问冲突等,并生成小转储文件。但是,如果由于未捕获的C++异常而终止,则当然不会调用该处理程序,因此也没有崩溃转储文件。
我目前正在寻找Windows解决方案(无论多么“肮脏”!),但如果可能,也想听听其他平台的建议。
谢谢。
3个回答

5
我们在上一个版本中使用了此网站提供的信息实现了未处理异常的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,直到我们选择了一个。这在真实世界中的崩溃中没有任何实际用途,因为在实现minidumps时我们不知道它们会是什么。它非常特定于应用程序,也特定于崩溃,因此我的建议是尽早添加minidump处理程序,它将随着项目的发展和QA而增长,并在某些时候(希望也在真实世界中)拯救生命。


2
这对于未捕获的C++异常确实有效(对于使用Visual Studio构建的应用程序而言)。我的最初误解是由于某个库深处隐藏的catch(...)块造成的...! - Steve Folly
一篇好文章!你使用了MiniDumpWriteDump(GetCurrentProcess()...),但MSDN说MiniDumpWriteDump()应该从一个单独的进程或至少从一个单独的线程中调用。你的代码不会导致错误的堆栈跟踪吗? - Elmue
我们当时得到的堆栈跟踪信息是正确的,但那是10年前的事情了,所以我无法验证那是否只是偶然事件,或者那些函数当时有不同的要求。请告诉我们你的进展情况,我很乐意更新答案以使其更加准确。 - Danny Parker

4
您可以使用try-except语句将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。 - David Haim

2
尝试使用 set_terminate 来安装终止处理程序。在其中使用迷你转储函数获取堆栈跟踪。也许这会起作用。

这正是我根据这篇文章所做的: http://www.codeproject.com/debug/XCrashReportPt1.asp - Bruce Ikin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接