Как предположил Мигель, правильный способ решения вашей проблемы, вероятно, заключается в использовании SetUnhandledExceptionFilter
.Но я все же хотел бы объяснить ваши феномены в деталях.
Прежде всего, не все сбои программы связаны с исключениями.Например, CRT может инициировать завершение программы при ошибках, таких как недопустимый доступ к элементу в vector
или вызов чисто виртуального деструктора.Если вы хотите охватить и эти случаи - см. set_unexpected
, set_terminate
и т. Д.
Кроме того, блок catch
может перехватывать только исключения, выданные из соответствующего блока кода.OTOH могут быть функции, которые вызываются в другом месте, такие как оконные процедуры (если применимо), другие потоки и т. Д.
Теперь относительно вашей проблемы.Давайте сначала поймем, почему такие вещи, как catch(...)
, могут отлавливать такие вещи, как нарушение доступа и т. Д., И почему это не всегда происходит (как в вашем случае).
В Windows предусмотрен собственный механизм обработки исключений - SEH, структурированныйОбработка исключений.Это намного превосходит обработку исключений в C ++.Кроме того, аппаратные прерывания (вызванные ЦП) автоматически «преобразуются» в исключения SEH, поэтому код, использующий SEH, обрабатывает как программные исключения, так и аппаратные сбои.
Компиляторы Microsoft C ++ фактически реализуют исключения C ++ черезSEH .То есть throw
реализуется через RaiseException
с указанием C ++-специфичного кода и параметров исключений, catch
является C ++ -специфичной оболочкой для __except
, и для каждого объекта с деструктором компилятор генерирует что-то похожее на __finally
блок.И это также работает наоборот.Когда возникает исключение не-C ++ - выполняется тот же код, сгенерированный для исключений C ++.
Кроме того, существуют так называемые параметры обработки исключений компилятора, которые влияют как на генерацию кода обработки исключений компилятора, так и на его поведение вво время выполнения.Они называются моделями обработки исключений:
- синхронный .Компилятор генерирует код, который гарантированно будет работать правильно, только если исключения вызываются явно.Это включает
throw
статистики и все «чужие» функции, чей код не виден компилятору (в некоторых вариантах - только внешние функции C ++).В частности, чтение из памяти считается «безопасным». - асинхронный .Компилятору не разрешается предполагать, что могут возникнуть исключения.Следовательно, он генерирует код, который должен работать правильно, даже если исключение возникает из-за доступа к адресу памяти.
Кроме того, код CRT, который вызывается в catch (...)
, намеренно игнорирует исключения не-C ++,если не выбрана асинхронная модель EH .
Так что, если вы хотите, чтобы catch (...)
перехватывал исключения не-C ++ - вы должны выбрать асинхронную модель EH.
Как только я написал статью по проекту кода , после того, как у меня возникла проблема в разработке драйверов.Это объясняет все это в деталях.