捕获未处理的异常

时间:2017-06-22 15:14:26

标签: c++ winapi exception-handling seh

在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:替换misunderstanded string * 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;
}

3 个答案:

答案 0 :(得分:3)

Per Remy的评论,访问冲突是Windows&#34;结构化例外,&#34;不是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!
}

答案 1 :(得分:0)

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

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

有关未定义行为的更多信息,请访问Undefined, unspecified and implementation-defined behavior

答案 2 :(得分:0)

*nullptr = 0xbad;

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

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

这就是为什么每个团队都应该有一位语言律师能够分辨出什么是UB。 UB的影响可能非常不合适,并且在某个晚些时候或之前的某个日期在整个计划中发生。这个人应该熟悉现代的,惯用的C ++,并负责创建或至少为团队创建编码标准提供大量的咨询。

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