16

如果发生未处理的 C++ 异常,我想打印:

  1. what()C++ 异常的消息 ( )
  2. 堆栈跟踪。

为了获取堆栈跟踪,我SetUnhandledExceptionFilter结合使用StackWalker库:

struct FooStackWalker : StackWalker
{
    virtual void OnCallstackEntry(CallstackEntryType, CallstackEntry &entry) override
    {
        std::cerr << entry.lineFileName << " (" << entry.lineNumber << "): " << entry.undFullName << std::endl;
    }
};

LONG WINAPI UnhandledExceptionHandler(LPEXCEPTION_POINTERS pointers)
{
    FooStackWalker walker;
    walker.ShowCallstack(::GetCurrentThread(), pointers->ContextRecord);
    ::TerminateProcess(::GetCurrentProcess(), 1);
}


int main()
{
    ::SetUnhandledExceptionFilter(UnhandledExceptionHandler);
}

我已经让堆栈跟踪打印得很好,但现在what很难。

有什么方法可以将 SEH 异常解码为 C++ 异常,以便在终止之前调用此成员函数?

4

2 回答 2

4

为什么不使用已经为您提供异常详细信息的 C++ 机制?它不是 SEH 过滤器独有的(尽管它独有的SetUnhandledExceptionFilter)。您只需要正确嵌套处理程序:

int main()
{
    try {
        return cppexcept_main();
    }
    catch (const std::exception& e)
    {
        //use e.what()
    }
}

int cppexcept_main()
{
    __try {
        return application_main();
    }
    __except(GrabStackTrace(GetExceptionInformation()), EXCEPTION_CONTINUE_SEARCH) {
         /* never reached due to EXCEPTION_CONTINUE_SEARCH */
    }
}
于 2014-07-04T20:15:51.240 回答
2

编辑:我误解了你的问题。我不能确定 C++ 异常的答案是什么,但我有理由确定答案是“否”。我不相信有任何方法可以区分由 SEH 引起的未处理异常(例如访问冲突)和未捕获的 C++ 异常,也没有任何方法可以区分不同类型的 C++ 异常。那匹马已经在那匹马上离开了谷仓。

原答案如下:


不,因为 SEH 异常没有what. 它不是一个std::exception. 这个 MSDN 示例说,当您尝试将 SEH 异常作为 C++ 异常捕获时,只能使用省略号 ( ...)catch处理程序来捕获它。您可以使用_set_se_translator定义自己的函数将 SEH 异常转换为 C++ 异常,但此时您只是what从不同位置的相同信息生成自己的函数(即使那样,我也不知道它是否会是可以从UnhandledExceptionFilter) 得到它。

您拥有LPEXCEPTION_POINTERS结构中所需的所有信息。如果发生访问冲突,pointers->ExceptionRecord->ExceptionCode则为EXCEPTION_ACCESS_VIOLATION(0xC0000005)。如果发生这种情况,那么您可以检查NumberParametersExceptionInformation变量以确定它是读取还是写入违规以及尝试访问的地址。

于 2012-10-30T22:38:17.757 回答