C++ 捕获未处理的异常

C++ 捕获未处理的异常,c++,winapi,exception-handling,seh,C++,Winapi,Exception Handling,Seh,在Windows中,我有一些线程。其中两个异常终止(例如,空指针解引用)。我有SetUnhandledExceptionFilter(…),它在第一个异常时开始生成转储。在第二个例外情况下,整个程序死亡。有没有办法处理这种情况?除第一个错误外,所有关键错误均应忽略 伪代码: void job() { ... RaiseException(someCode, someFlags, 0, nullptr); // or doing something wrong, like nu

在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:忘记nullptr吧

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;
}
#包括
#包含//用于异常\u访问\u冲突
#包括
#包括
长型stdcall HandleException(异常指针*exinfo)
{
静态句柄互斥=CreateMutex(nullptr,FALSE,uu TEXT(“HandleException”);
while(WaitForSingleObject(互斥,无限)!=WAIT\u OBJECT\u 0);
HANDLE event=CreateEvent(nullptr、TRUE、FALSE、_文本(“正在转储”);
卖出(“卖出”);
WaitForSingleObject(事件,5000);//执行转储例程
看跌期权(“看跌期权”);
返回异常\u执行\u处理程序;
}
整型过滤器(无符号整型代码,结构异常指针*ep)
{
放入(“过滤器中”);
返回句柄异常(ep);
}
作废职务()
{
放置(“你好”);
int*p=0x00000000;//指向NULL的指针
*p=13;//导致访问冲突异常;
}
作废安全工单(作废(*工单)()
{
__试一试{
job();
}_uu除了(过滤器(GetExceptionCode(),GetExceptionInformation()){
出口(-1);
}
}
int main()
{
SetUnhandleExceptionFilter(HandleException);
std::线程t1(std::bind(safeJob,Job));
std::线程t2(std::bind(safeJob,Job));
t1.join();
t2.连接();
返回0;
}

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

最好避免编写这样的代码


有关未定义行为的更多信息,请访问。

*nullptr=0xbad

你造成了未定义的行为。在这之前,您甚至不能期望代码正常运行。由于编译器优化和它必须假定UB不会发生的权限,未定义的行为在命中之前会及时产生影响

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

这就是为什么每个团队都应该有一个语言律师,他能说出什么是UB。UB的影响可以是非常离谱的,并且在稍后或之前的某个日期发生在整个程序中。这个人应该熟悉现代的、习惯性的C++,并负责创建,或者至少对团队的编码标准进行巨大的咨询。
第二个要求应该是执行律师。有人可以告诉你从UB期望什么。这是一种更先进的…比科学更神奇的东西。他们知道的并不总是这样,UB活动的领域是巨大的!这些家伙不是在树上生长的——我没有资格,除非是在极简主义的水平上。

< P> > ReMy的评论,访问冲突是Windows“结构化异常”,而不是C++异常,它可以用微软特定的扩展来处理,比如一个尝试语句。

例如:

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

听起来像是
getDump
中的错误。请显示您的实际代码。
nullptr
取消引用不一定会引发异常,这是未定义的行为。我不知道任何系统在取消引用
nullptr
时会引发异常。它要么因segfault崩溃,要么什么也不做(尽管它可以像UB一样做任何事情)。取消引用std::nullptr_t
是一个编译错误,应该类似于
*(int*)nullptr=0xbad
@Kevin:该系统称为“Windows”。winapi标记应该已经暗示了这一点。实际上,这个系统叫做英特尔x86。英特尔(和compatibles)上所谓的“segfault”是指CPU生成异常(如果我没记错的话,是GPF),Windows实际上保留了这个术语。我只听说过这些UB-gurus的传说一般来说,这是一个很好的建议,但并不真正适用于OPs案例,因为他已经知道他正在得到一个例外,并正在试图解决这个问题。更重要的是,他知道他正在获得一个“结构化异常”——这是一个WiAPI的东西,而不是C++异常。如果程序取消了一个NulLPTR,那么编程语言(C++)就不能保证应该发生什么。而另一方面,平台(Windows)则起作用。它会引发访问冲突异常。@IInspectable,但在Windows上不会显示可预测和可靠的行为。例如,Windows编译器仍可能以这种方式运行。第一个示例显示了一种情况,在这种情况下,您可能期望出现异常,但没有得到异常;第二个示例显示了一个案例,在这个案例中,您将得到一个您没有预料到的异常。(VisualStudio 2015,在发布模式下,执行前者,但没有任何规则表明Windows编译器也不能执行后者。)您可以对此答案添加解释吗?在Windows上,取消空指针引发SEH <代码>异常访问Access违规< /COR>异常,而不是C++异常。代码>\uuuuu try/\uuuuuu除外可用于处理SEH异常。有关更多详细信息,请参见MSDN。一般来说,这是一个很好的建议,但实际上并不适用于OPs案例,因为他已经知道自己遇到了异常,并正在尝试解决问题。是的,没错。由于访问零大小容器而导致的空指针解引用,而不是通过明确地这样做。编程语言(C++)不保证在程序