Исключение - это событие, которое происходит во время выполнения программы и требует выполнения кода вне обычного потока управления. Есть два вида исключений: исключения оборудования и исключения программного обеспечения. Аппаратные исключения инициируются ЦП. Они могут возникать в результате выполнения определенных последовательностей инструкций, таких как деление на ноль или попытка доступа к недопустимому адресу памяти. Исключения программного обеспечения инициируются явно приложениями или операционной системой. Например, система может обнаружить, когда указано недопустимое значение параметра.

Исключения, такие как Нарушение прав доступа и Делить на ноль, являются аппаратными исключениями. С параметрами компилятора / 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). Это делает ваш код более портативным и гибким.