Исключение - это событие, которое происходит во время выполнения программы и требует выполнения кода вне обычного потока управления. Есть два вида исключений: исключения оборудования и исключения программного обеспечения. Аппаратные исключения инициируются ЦП. Они могут возникать в результате выполнения определенных последовательностей инструкций, таких как деление на ноль или попытка доступа к недопустимому адресу памяти. Исключения программного обеспечения инициируются явно приложениями или операционной системой. Например, система может обнаружить, когда указано недопустимое значение параметра.
Исключения, такие как Нарушение прав доступа и Делить на ноль, являются аппаратными исключениями. С параметрами компилятора / EHsc (по умолчанию) или / EHs C ++ не обрабатывает эти аппаратные исключения, используя стандартную Обработку исключений C ++ try и блок catch. Приведенная ниже программа выйдет из строя из-за необработанного аппаратного исключения, если используется параметр компилятора / EHsc или / EHs.
Существует простой способ перехвата как стандартных исключений C ++ (программных исключений), так и аппаратных исключений с помощью блока обработки исключений C ++ try и catch. Просто включите параметр компилятора / EHa в настройках проекта в Visual Studio (Свойства проекта - ›C / C ++ -› Создание кода - › Измените Включить исключения C ++ на «Да с исключениями SEH (/ EHa)»). При использовании этого параметра компилятора / EHa указанная ниже программа не аварийно завершает работу, поскольку будет перехвачено исключение.
#include <iostream> using namespace std; void TestMethod() { int i = 0, j = 1; j = j / i; // This will throw Divide by Zero exception } int main() { try { TestMethod(); } // catch block will not be executed for /EHsc or /EHs // catch block will be executed for /EHa catch(...) { cout << "An exception was caught." << endl; } }
В качестве альтернативы, программы на C и C ++ могут использовать механизм Структурированной обработки исключений (SEH) в операционной системе Windows для идентичной обработки аппаратных и программных исключений. Концепции SEH напоминают концепции Обработки исключений C ++, за исключением того, что SEH использует конструкции __try, __except и __finally вместо попробовать и поймать.
// compile with: /EHsc, /EHs, or /EHa #include <iostream> #include <excpt.h> using namespace std; void TestMethod() { int i = 0, j = 1; j = j / i; // This will throw Divide by Zero exception } int main() { __try { TestMethod(); } // __except will catch the exception here. __except(EXCEPTION_EXECUTE_HANDLER) { cout << "An exception was caught in __except." << endl; } } Output: An exception was caught in __except.
В параметре компилятора / EHa, если аппаратное исключение возникает в программе на C ++, оно может обрабатываться структурированным обработчиком исключений с соответствующим фильтром или уловкой C ++. обработчик, в зависимости от того, что динамически ближе к контексту исключения. Например, этот пример программы на C ++ вызывает аппаратное исключение внутри контекста try C ++:
// compile with: /EHa #include <iostream> using namespace std; void SEHFunc() { __try { int x, y = 0; x = 5 / y; } __finally { cout << "In finally." << endl; } } int main() { try { SEHFunc(); } catch(...) { cout << "An exception was caught in catch."<< endl; } } Output: In finally. An exception was caught in catch.
Разница между структурированной обработкой исключений и стандартной обработкой исключений C ++:
Основное различие между структурированной обработкой исключений (SEH) и стандартной обработкой исключений C ++ заключается в том, что модель обработки исключений C ++ имеет дело с типами, тогда как модель обработки структурированных исключений C работает с исключениями одного типа; в частности, беззнаковое целое. То есть структурированные исключения C идентифицируются целочисленным значением без знака, тогда как исключения C ++ идентифицируются по типу данных.
Второе отличие состоит в том, что структурированная модель обработки исключений называется асинхронной, поскольку исключения возникают вторично по отношению к нормальному потоку управления. Механизм обработки исключений C ++ полностью синхронный, что означает, что исключения возникают только при их возникновении.
Резюме:
- Параметр компилятора / EHa поддерживает обработку как стандартных исключений C ++ (программных исключений), так и исключений оборудования с помощью предложений C ++ try и catch. Чтобы реализовать SEH без указания / EHa, вы можете использовать синтаксис __try, __except и __finally.
- Указание / EHa и попытка обработать все исключения с помощью catch (…) могут быть опасными. В большинстве случаев асинхронные исключения не подлежат восстановлению и должны считаться фатальными. Их перехват и дальнейшие действия могут вызвать повреждение процесса и привести к ошибкам, которые трудно найти и исправить.
- Когда вы используете / EHsc или / EHs, компилятор предполагает, что исключения могут возникать только в инструкции throw или при вызове функции. Это предположение позволяет компилятору исключить код для отслеживания времени жизни многих разворачиваемых объектов, что может значительно уменьшить размер кода. Если вы используете / EHa, ваш исполняемый образ может быть больше и медленнее, потому что компилятор не так агрессивно оптимизирует блоки try. Он также оставляет фильтры исключений, которые автоматически очищают локальные объекты, даже если компилятор не видит никакого кода, который может вызвать исключение C ++.
- Структурированная обработка исключений (SEH) - это расширение Microsoft для языка C, предназначенное для корректной обработки определенных исключительных ситуаций кода, таких как сбои оборудования. Хотя Windows и Microsoft Visual C ++ поддерживают SEH, мы настоятельно рекомендуем использовать обработку исключений C ++ по стандарту ISO (с / EHsc или / EHs). Это делает ваш код более портативным и гибким.