Обработка исключительных ситуаций

Язык C++ / Обработка исключительных ситуаций

Исключение — это событие при выполнении программы, которое приводит к её ненормальному или неправильному поведению.
Существует два вида исключений:

  • Аппаратные (структурные, SE-Structured Exception), которые генерируются процессором. К ним относятся, например,
    • деление на 0;
    • выход за границы массива;
    • обращение к невыделенной памяти;
    • переполнение разрядной сетки.
  • Программные, генерируемые операционной системой и прикладными программами – возникают тогда, когда программа их явно инициирует. Когда встречается аномальная ситуация, та часть программы, которая ее обнаружила, может сгенерировать, или возбудить, исключение.

Механизм структурной обработки исключений позволяет однотипно обрабатывать как программные, так и аппаратные исключения.

Обработка программных исключений

Фундаментальная идея обработки исключительных ситуаций состоит в том, что функция, обнаружившая проблему, но не знающая как её решить, генерирует исключение в надежде, что вызвавшая её (непосредственно или косвенно) функция сможет решить возникшую проблему. Функция, которая может решать проблемы данного типа, указывает, что она перехватывает такие исключения.

Для реализации обработки исключений в C++ используйте выражения try, throw и catch.
Блок try {...} позволяет включить один или несколько операторов, которые могут создавать исключение.
Выражение throw используется только в программных исключениях и означает, что исключительное условие произошло в блоке try. В качестве операнда выражения throw можно использовать объект любого типа. Обычно этот объект используется для передачи информации об ошибке.
Для обработки исключений, которые могут быть созданы, необходимо реализовать один или несколько блоков catch сразу после блока try. Каждый блок catch указывает тип исключения, которое он может обрабатывать.
Сразу за блоком try находится защищенный раздел кода. Выражение throw вызывает исключение, т.е. создает его.
Блок кода после catch является обработчиком исключения. Он перехватывает исключение, вызываемое, если типы в выражениях throw и catch совместимы. Если оператор catch задает многоточие (...) вместо типа, блок catch обрабатывает все типы исключений.
Поскольку блоки catch обрабатываются в порядке программы для поиска подходящего типа, обработчик с многоточием должен быть последним обработчиком для соответствующего блока try. Как правило, блок catch(...) используется для ведения журнала ошибок и выполнения специальной очистки перед остановкой выполнения программы.

try { ... // защищенный раздел кода
  throw параметр;
}
catch (параметр) { // обработка исключения }
catch (...) { // обработка остальных исключений }

Ниже приведен пример обработки программного исключения. В реальных программах посылка исключения командой throw, как правило, является следствием проверки какого-либо условия.

#include <iostream>
using namespace std;
int main() {
  try {
    cout << "Exception: ";
    throw 1;
    cout << "No exception!";
  } catch (int a) {
    cout << a;
  }
cin.get(); return 0;
}
#include <iostream>
using namespace std;
int main() {
  try {
    cout << "Exception: ";
    //throw 1;
    cout << "No exception!";
  } catch (int a) {
    cout << a;
  }
cin.get(); return 0;
}
 Исключение  throw  Исключение throw
Обработка структурных исключений

Рассмотрим пример программы, генерирующей исключительную ситуацию "деление на 0".

#include <iostream>
using namespace std;
int main() {
  int a = 0, b =10;
  cout << b/a << endl;cin.get();
  return 0;
}

При попытке запустить программу на выполнение видим следующее:

Необработанное исключение

Для обработки исключительной ситуации необходимо операцию деления поместить в блок защищенного кода:

#include <iostream>
using namespace std;
int main() {
  int a = 0, b = 10;
  try {
    cout << b / a << endl;
  }
  catch (...)
  {
    cout << "error";
  }
  cin.get();
  return 0;
}

Для корректного запуска программы необходимо также произвести настройки среды разработки и разрешить обработку структурных исключений. Для этого переходим к меню Имя проекта->Свойства
Имя проекта - Свойства
И для пункта меню C/C++ ->Code Generation->Enable C++ Exceptions устанавливаем значение Yes With SEH Exceptions (/EHa).
SH исключения
При запуске программы на выполнение имеем следующий результат:
Обработка аппаратных исключений

При компиляции с параметром /EHa, в число обрабатываемых исключений могут входить структурированные исключения C и создаваемые системой или приложением асинхронные исключения, например нарушения, связанные с защитой памяти, делением на ноль и числами с плавающей запятой.
Назад

Комментариев к записи: 6

  • Fancy Pants 3

    Обработка исключительных ситуаций самой программой заключается в том, что при возникновении исключительной ситуации управление передаётся некоторому заранее определённому



  • Блог программиста

    Хотел написать у себя статью про обработку исключений, но слишком сложно. Я не осилил.

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

    — приведение типа (throw 1; catch(float) или наоборот);

    — передачу исключений по значению, ссылку и указателю;

    — спецификации исключений.

    Реально вопрос очень сложный, так например у Маерса половина книжки посвящена этому вопросу. Но Маерс писал книжки давно и много внимания освятил спецификациям, но с тех пор, как вышел C++11 на MSDN можно найти статью, в которой пишут, что в современном С++ спецификации использовать не желательно.

    Тем не менее, внимание этому (в статье) уделить все равно надо, т.к. спецификации из языка никто не убрал и в других языках (например Java) с ними никаких проблем нет. Т.е. пока что не очень очевидно как пользоваться всем этим в С++ (Маерс тоже писал про это, типа «разработчики компиляторов сами имеют недостаточный опыт работы с исключениями, поэтому …»).

    В общем, тема скользкая — я уже больше двух лет не могу решиться написать статью по этой теме )


    • Мало ли у кого там скока в книжке написано статься замечательная больше 2 лет не можешь приступить к написании статьи это абсурд а тут уже написано это просто конструкции и никакие книжки тут ненужны как говориться

      Сначала учите науку программирования и всю теорию. Далее выработаете свой программистский стиль. Затем забудьте все и просто программируйте.
      — George Carrette


      • Блог программиста

        Школу закончи и знаки препинания расставлять научись. Про «тся» и «ться» прочитать не забудь.

         


Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *