相关文章推荐

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement . We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

I allways use Windows Function SetUnhandleExceptionFilter to handle process exception, but wen i handle thread exception, find it's not work. here is the code

#include <thread>
#include <Windows.h>
std::unique_ptr<std::thread> g_thread;
static LONG WINAPI handleExcept(EXCEPTION_POINTERS* p)
    printf("handle exception\n");
    return EXCETPION_CONTINE_SEARCH;
void crash_thread_throw()
    g_thread.reset(new std::thread([](){
        throw "";
void crash_thread_ptr()
    g_thread.reset(new std::thread([](){
        int* a = nullptr;
        a[0] = 1;
int main()
    auto filter = SetUnhandleExceptionFilter(handleExcept);
    crash_thread_throw();
    // crash_thread_ptr(); // this can be handle
    return 0;
std::unique_ptr<std::thread> g_thread;
static LONG WINAPI handleExcept(EXCEPTION_POINTERS* p)
    printf("handle exception\n");
    return EXCEPTION_CONTINUE_EXECUTION;
void crash_thread_throw()
    g_thread.reset(new std::thread([]() {
        throw "";
void crash_thread_ptr()
    g_thread.reset(new std::thread([]() {
        int* a = nullptr;
        a[0] = 1;
int main()
    //auto filter = SetUnhandledExceptionFilter(handleExcept);
    PVOID h1 = AddVectoredExceptionHandler(0, handleExcept);
    crash_thread_throw();
    // crash_thread_ptr(); // this can be handle
    g_thread->join();
    RemoveVectoredExceptionHandler(h1);
    return 0;

I'm not an expert with handling process exception but I googled and I found: https://stackoverflow.com/questions/69009598/exception-thrown-in-stdthread-cant-trigger-function-set-by-setunhandledexcept and https://stackoverflow.com/a/54879453

By the way, @AlexGuteniev I found your answer at StackOverflow

thank for your answer, I know VEH can handle this exception, and i'm not an expert too (O.o). I want to know why SetUnhandleExceptionFilter doesn't work, in code stack, has other dlls called after KernelBase.dll .Before your answer, I guess maybe std::thread do something, after browse your googled answer, I'm sure my guess, but i don't hava other dll's pdb, so i want to know what happened after KernelBase.dll.
@AlexGuteniev, please help me

std::thread throw an excepition, main thread con't make dmp std::thread throw an exception, main thread can't make dmp Dec 13, 2023

@StephanTLavavej , original code has 2 typos.

EXCETPION_CONTINE_SEARCH => EXCEPTION_CONTINUE_EXECUTION

SetUnhandleExceptionFilter => SetUnhandledExceptionFilter

#include <thread>
#include <Windows.h>
std::unique_ptr<std::thread> g_thread;
static LONG WINAPI handleExcept(EXCEPTION_POINTERS* p)
    printf("handle exception\n");
    return EXCEPTION_CONTINUE_EXECUTION;
void crash_thread_throw()
    g_thread.reset(new std::thread([](){
        throw "";
void crash_thread_ptr()
    g_thread.reset(new std::thread([](){
        int* a = nullptr;
        a[0] = 1;
int main()
    auto filter = SetUnhandledExceptionFilter(handleExcept);
    crash_thread_throw();
    // crash_thread_ptr(); // this can be handle
    g_thread->join();
    return 0;

it doesn't need any flags and it can be compiled with

cl test.cpp
          

You're throwing a C++ exception, which is subject to C++ noxcept rules. std::thread::_Invoke, the thread procedure for _beginthreadex, is noexcept, so std::terminate will be called on an exception, which ultimately results in STATUS_FATAL_APP_EXIT which can't be caught with an unhandled exceptiion filter.

https://github.com/microsoft/STL/blob/a8888806c6960f1687590ffd4244794c753aa819/stl/inc/thread#L56C35-L56C35

And even if _Invoke wasn't noexcept, the UCRT is almost certainly compiled with /EHsc (extern "C" implies noexcept), so a C++ exception wouldn't be handed down to the unhandled exception filter anyway.

I can agree with @Fulgen301 that this is standard

Literally - it is mandated by [thread.thread.constr]/5:

If the invocation of invoke terminates with an uncaught exception, terminate is invoked (14.6.2).

the thread procedure for _beginthreadex, is noexcept, so std::terminate will be called on an exception, which ultimately results in STATUS_FATAL_APP_EXIT which can't be caught with an unhandled exceptiion filter.

AddVectoredExceptionHandler can handle this, but i don't know the underlying logic of it, So I'm not sure if it's the opposite of what you say.

Vectored exception handlers are called from where the SEH exception is thrown before the stack is being unwound or any frame handlers are called. Note that that includes both C++ and SEH exceptions that may actually be caught with try - catch / __try - __except.

On the contrary, the unhandled exception filter is only called on unhandled exceptions. From a C++ point of view, the exception travels up the stack until it hits the noexcept from the thread procedure which results in std::terminate being called. This is the behavior the C++ standard mandates. However, from a SEH point of view, there is no unhandled exception in that chain - it travels up the stack until the frame handler that is the noexcept machinery handles it. If that thread procedure wasn't noexcept (violating the C++ standard) and the thread procedure caller in the UCRT wasn't noexcept either (fun with ABI since you're now throwing exceptions over a DLL boundary if the CRT is linked dynamically), _seh_filter_exe / _seh_filter_dll would be called, which doesn't handle the C++ exception SEH code, so the SEH exception would ultimately end up unhandled, causing the unhandled exception filter to be called.

(And STATUS_FATAL_APP_EXIT / __fastfail is special and can't be caught using unhandled exception filters because it's designed that way.)

 
推荐文章