Win10,VS2019
代码如下:
LONG __stdcall DummyUnhandledExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo)
{
printf("DummyUnhandledExceptionFilter called\n");
return EXCEPTION_CONTINUE_SEARCH;
}
int wmain(const int argc, const wchar_t* argv[])
{
SetUnhandledExceptionFilter(DummyUnhandledExceptionFilter);
std::thread crash(
[]()
{
Sleep(1 * 1000);
auto pOld = SetUnhandledExceptionFilter(NULL);
if (pOld != &DummyUnhandledExceptionFilter)
{
printf("unequal\n");
}
SetUnhandledExceptionFilter(pOld);
#if 0
RaiseException(0, 0, 0, 0); //可以触发
#elif 1
throw std::exception(); //不能触发
#else
int* p = 0;
p[0] = 1; //可以触发
#endif
}
);
crash.join();
}
在非主线程里,这三种触发异常的代码的行为不一样,RaiseException和空指针的访问违规是可以调用到DummyUnhandledExceptionFilter的,但是C++ 的throw并不能。(如果是在主线程throw,是可以调用到DummyUnhandledExceptionFilter)
在《Windows核心编程》第五版25.5节(683页)里说:
“我们应该了解Microsoft的Visual C++编译器使用操作系统的结构化异常机制来实现C++异常处理机制。……编译器也会为C++ throw语句生成对Window RaiseException函数的调用……”
按这个说法,前两种触发异常的方式的效果应该是一样的,但是现在效果确实不一样。而且我在汇编里跟踪,throw时也确实调用了RaiseException,是通过_CxxThrowException函数来进行的,但是最终效果应该一样吧,但是为什么throw就是不能调用到DummyUnhandledExceptionFilter呢?
我在写这个问题的时候查到了std::set_terminate函数,但是这个函数也调用不到设置的terminate_handler。在Debug模式下倒是可以。
请问哪位可以帮我理清这些东西的行为吗?或者给个链接、书的章节等,都可以,谢谢!