捕获未经处理的异常

Catching unhandled exceptions

本文关键字:异常 处理      更新时间:2023-10-16

在Windows中,我有一些线程。其中两个异常终止(例如,空指针取消引用)。我有SetUnhandledExceptionFilter(...)在第一个异常时开始生成转储。在第二个例外情况下,整个程序死亡。有没有办法处理这种情况?除第一个错误外,所有严重错误都应忽略。

伪代码:

void job()
{
...
RaiseException(someCode, someFlags, 0, nullptr); // or doing something wrong, like nullptr dereference
}
int main() {
SetUnhandledExceptionFilter(getDump);
std::thread t1(job), t2(job); 
...
}

UPD:替换误解的字符串 *nullptr = 0xbad;

UPD2:忘记空点

UPD3:到目前为止,我找到了这个解决方法

#include <stdio.h>
#include <windows.h>  // for EXCEPTION_ACCESS_VIOLATION
#include <excpt.h>
#include <mutex>

LONG __stdcall HandleException(EXCEPTION_POINTERS* exinfo)
{
static HANDLE mutex = CreateMutex(nullptr, FALSE, __TEXT("HandleException"));
while(WaitForSingleObject(mutex, INFINITE) != WAIT_OBJECT_0);
HANDLE event = CreateEvent(nullptr, TRUE, FALSE, __TEXT("Doing Dump"));
puts("Doing Dump");
WaitForSingleObject(event, 5000); // do dump routine
puts("Done Dump");
return EXCEPTION_EXECUTE_HANDLER;
}
int filter(unsigned int code, struct _EXCEPTION_POINTERS *ep)
{
puts("in filter.");
return HandleException(ep);
}
void Job()
{
puts("hello");
int *p = 0x00000000;  // pointer to NULL
*p = 13;  // causes an access violation exception;
}
void safeJob(void (*job)())
{
__try {
job();
} __except (filter(GetExceptionCode(), GetExceptionInformation())) {
exit(-1);
}
}
int main()
{
SetUnhandledExceptionFilter(HandleException);
std::thread t1(std::bind(safeJob, Job));
std::thread t2(std::bind(safeJob, Job));
t1.join();
t2.join();
return 0;
}

根据 Remy 的评论,访问冲突是 Windows"结构化异常",而不是C++异常,可以使用特定于Microsoft的扩展(如 try-except 语句)进行处理。

https://msdn.microsoft.com/en-us/library/s58ftw19.aspx

例:

__try
{
// doing something wrong
*nullptr = 0xbad;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
// exception quashed!
}

有一种误解,认为"做坏事"会引发异常。这是不正确的。如果您正在做的事情是导致未定义行为的原因,则不应期望任何可预测的行为。如果您的平台抛出异常,那很好,但要意识到您不能指望它。

最好的办法是避免编写此类代码。

有关未定义行为的更多信息,请参阅未定义、未指定和实现定义的行为。

*nullptr = 0xbad;

您导致了未定义的行为。 在它正确运行之前,您甚至不能期望该代码。 由于编译器优化以及它必须假定 UB 不会发生的权利,未定义的行为可能会在命中之前及时产生影响。

没有办法保护自己免受UB的侵害。您必须实现代码标准,以阻止或消除导致错误的类型的可能性。 这是您唯一能做的保护自己免受UB侵害的事情 - 不要创建它。

这就是为什么每个团队都应该有一个语言律师,他可以分辨什么是UB。 UB的效果可能非常不合时宜,并且在以后或以前的某个日期在整个程序中都很明显。 这个人应该熟悉现代的惯用C++,并负责创建,或者至少发挥巨大的建议,以创建编码标准的团队。

第二个要求应该是执行律师。 可以告诉您对UB的期望的人。 这是一个更高级的...比科学更神奇的东西。 他们所知道的并不总是这样,UB活动的领域是巨大的! 这些家伙不长在树上——除了在非常简约的水平上,我没有资格。