Что я должен знать о структурированных исключениях (SEH) в C++?

Какие важные моменты о структурированных исключениях должен знать каждый разработчик C++?

4 ответа

Решение

Они эквивалентны Win32 сигналам Unix и позволяют вам отлавливать исключения процессора, такие как нарушение доступа, недопустимые инструкции, деление на ноль.

С правильными параметрами компилятора (/EHa для Visual C++) исключения C++ используют тот же механизм, что и разматывание стека работает правильно как для исключений C++ (пользователь), так и для исключений SEH (OS).

В отличие от исключений C++, SEH не является типизированным, но все они имеют одинаковую структуру данных, которая имеет код исключения (причину) и дополнительную информацию о том, какой код неисправен и что хранится в процессоре во время сбоя. Увидеть GetExceptionCode а также GetExceptionInformation для более подробной информации об этом.

Кроме того, SEH имеет обработку "первого шанса", которая позволяет вам регистрировать или иным образом обрабатывать исключение, прежде чем раскручивание уничтожит все локальные переменные.

Недавно у меня была проблема, которая была косвенно вызвана SEH, в частности из-за одной особенности SEH, о которой, я думаю, должен знать каждый разработчик:

Когда используется SEH, деструкторы не вызываются, поэтому, если у вас есть код очистки в вашем деструкторе, он не будет очищен.

Наша проблема была вызвана критической секцией, которая была обернута объектом с Lock в конструкторе и Unlock в деструкторе.

У нас возникла тупиковая ситуация, и мы не могли понять, почему, и примерно после недели копания кода, дампов и отладки мы наконец поняли, что это потому, что было исключение, которое было обработано COM и заставляющее секцию Critical оставаться заблокированной, Мы изменили флаг компиляции в VS в свойствах проекта, которые говорят ему запускать деструкторы даже для SEH, и это решило проблему.

Таким образом, даже если вы не можете использовать SEH в своем коде, вы можете использовать библиотеку, которая использует (например, COM) и которая может вызвать неожиданное поведение.

Ускоренный курс по глубине структурной обработки исключений Win32™

Эта статья - справочник по освоению с SEH. 13 лет спустя все еще остается лучшим.

Существует специальная тема по MSDN для SEH и C++. Различия в обработке исключений.

Некоторые вещи, которые разработчик C++ должен знать, обсуждается ли SEH:

Написание C / C++ SEH обработчиков исключений:

__try 
{
   // guarded code
}
__except ( expression )
{
   // exception handler code
}

Это не обработка исключений в C++, это специфичные для MS расширения для перехвата прямого доступа в SEH. Он работает совсем не так, как ваши обычные исключения C++. Вам нужно хорошее понимание SEH, чтобы использовать их.

Написание обработчиков завершения C / C++ SEH:

__try {
   // guarded code
}
__finally ( expression ) {
   // termination code
}

Как и в случае с обработчиком SEH, не путайте это с семантикой исключений C++. Вам нужно хорошее понимание SEH.

_set_se_trasnlator: эта функция преобразует исключения SEH в исключения типа C++, когда используются асинхронные исключения / EHa.

И, наконец, личное мнение: должен ли C++ разработчик знать SEH? После вашего первого новобранца .ecxr вы поймете, что когда дело доходит до распространения, исключения C++ - это всего лишь иллюзия, предоставленная для вашего удобства. Единственное, что происходит, это SEH.

Они должны знать, что они не являются частью стандарта C++ - они являются изобретением Microsoft и могут использоваться на языках, отличных от C++.

Важный момент - знать, когда использовать SEH, а когда - стандартные исключения C++. Во-первых, выберите только одну систему - системы смешивания обычно проблематичны, требуя глубокого понимания обеих для правильной реализации. Во-вторых, на высоком уровне SEH не ограничивается C++, тогда как стандартные исключения C++ не ограничиваются Windows. Если это не диктует ваше решение, выберите стандартные исключения, если они не подходят (см. Другие ответы для получения дополнительных сведений о том, что может делать SEH).

Цитата из документации Microsoft (от 13.08.2018) подтверждает этот вывод.

Структурированная обработка исключений (SEH) - это расширение Microsoft для языка C, предназначенное для корректной обработки определенных исключительных ситуаций кода, таких как сбои оборудования. Хотя Windows и Microsoft C++ поддерживают SEH, мы рекомендуем использовать обработку исключений C++ по стандарту ISO, поскольку это делает ваш код более переносимым и гибким. Тем не менее, для поддержки существующего кода или для определенных типов программ вам все равно, возможно, придется использовать SEH.

Почему автор расширения рекомендует не использовать его в большинстве случаев? Предположительно потому, что расширение было написано для C, а текущий контекст - C++. Языки схожи, поэтому перенос SEH на C++ в качестве побочного преимущества, вероятно, был достаточно легким, даже несмотря на то, что только "определенные типы программ" действительно выиграли бы. (Или, возможно, по какой-то другой причине; возможно, портирование было начато до стандартизации C++. История становится запутанной.)

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