Поймать необработанные исключения

В 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;
}

3 ответа

Согласно комментарию Реми, нарушение доступа - это "структурированное исключение" Windows, а не исключение C++, и оно может быть обработано с помощью расширений, характерных для Microsoft, таких как оператор try-exc.

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 ОГРОМНА! Эти парни не растут на деревьях - я не готовлюсь, кроме как на очень минималистичном уровне.

Другие вопросы по тегам