#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.)