Reputation: 68638
Is there any way I can get the .what()
of an uncaught C++ exception while also having a windows unhandled exception filter installed?
To demonstrate, the following program...
#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");
}
outputs:
FOO
I want it to output either BAR
or FOOBAR
Commenting out the SetUnhandledExceptionFilter
makes it work (but that's unacceptable as it won't catch the other windows exception types).
Clearly SetUnhandledExceptionFilter
somehow overrides std::set_terminate
in some way?
Upvotes: 1
Views: 1022
Reputation: 33706
all c++ exceptions internal use throw keyword. internal it use _CxxThrowException
and this api call RaiseException
function with 0xE06D7363
in place dwExceptionCode. so you need call previous exception filter returned by SetUnhandledExceptionFilter
for C++ exceptions if want handle it with TerminateHandler
.
g_prevlpTopLevelExceptionFilter = SetUnhandledExceptionFilter(WindowsExceptionHandler);
and
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";
}
Upvotes: 5