繁体   English   中英

如何将 std::set_terminate 与 SetUnhandledExceptionFilter 一起使用?

[英]How to use std::set_terminate with SetUnhandledExceptionFilter?

有什么方法可以让我获得未捕获的 C++ 异常的.what() ,同时还安装了 Windows 未处理的异常过滤器?

为了演示,以下程序...

#include <windows.h>
#include <iostream>

static LONG WINAPI WindowsExceptionHandler(LPEXCEPTION_POINTERS ep) {
    std::cerr << "FOO" << std::endl;
    return EXCEPTION_EXECUTE_HANDLER;
}

void TerminateHandler() {
    std::exception_ptr exception_ptr = std::current_exception();
    try {
        if (exception_ptr) std::rethrow_exception(exception_ptr);
    } catch (const std::exception& e) {
        std::cerr << e.what() << std::endl;
    }
}

int main() {
    SetUnhandledExceptionFilter(WindowsExceptionHandler);
    std::set_terminate(TerminateHandler);
    throw std::runtime_error("BAR");
}

输出:

FOO

我希望它输出BARFOOBAR

注释掉SetUnhandledExceptionFilter使其工作(但这是不可接受的,因为它不会捕获其他 Windows 异常类型)。

显然SetUnhandledExceptionFilter以某种方式覆盖了std::set_terminate

所有 C++ 异常内部都使用throw关键字。 内部它使用_CxxThrowException和这个 api 调用RaiseException函数与0xE06D7363就地dwExceptionCode 因此,如果要使用TerminateHandler处理它,则需要调用SetUnhandledExceptionFilter为 C++ 异常返回的先前异常过滤器。

g_prevlpTopLevelExceptionFilter = SetUnhandledExceptionFilter(WindowsExceptionHandler);

if (ExceptionRecord->ExceptionCode == 0xE06D7363) {
    return g_prevlpTopLevelExceptionFilter(ep);
}

LPTOP_LEVEL_EXCEPTION_FILTER g_prevlpTopLevelExceptionFilter;

LONG WINAPI WindowsExceptionHandler(LPEXCEPTION_POINTERS ep) {

    PEXCEPTION_RECORD ExceptionRecord = ep->ExceptionRecord;

    printf("%s: %x at %p", __FUNCTION__, 
        ExceptionRecord->ExceptionCode, ExceptionRecord->ExceptionAddress);

    if (ULONG NumberParameters = ExceptionRecord->NumberParameters)
    {
        printf(" { ");
        PULONG_PTR ExceptionInformation = ExceptionRecord->ExceptionInformation;
        do 
        {
            printf(" %p", (void*)*ExceptionInformation++);
        } while (--NumberParameters);
        printf(" } ");
    }

    printf("\n");

    if (ExceptionRecord->ExceptionCode == 0xE06D7363) {
        return g_prevlpTopLevelExceptionFilter(ep);
    }

    return EXCEPTION_EXECUTE_HANDLER;
}

void TerminateHandler() {
    MessageBoxW(0, 0, __FUNCTIONW__, MB_ICONWARNING);
    exit(-1);
}

void main() {
    g_prevlpTopLevelExceptionFilter = 
        SetUnhandledExceptionFilter(WindowsExceptionHandler);
    set_terminate(TerminateHandler);
    throw "888";
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM