4887

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

Лекция

Информатика, кибернетика и программирование

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

Русский

2012-11-28

43.5 KB

3 чел.

Обработка исключений.

Исключением называют возникновение «аномальной» ситуации во время выполнения, которое программа может обнаружить, например: деление на 0, выход за границы массива или отсутствие требуемого количества свободной памяти. Такие ситуации нарушают нормальный ход работы программы и требуют немедленной реакции. В C++ имеются встроенные средства для оповещения об исключительной ситуации и её обработки. С помощью этих средств активизируется механизм, позволяющий двум несвязанным (или независимо разработанным) фрагментам программы обмениваться информацией об исключении.

Без использования механизма исключений обработка ошибок часто реализуется громоздким и навязчивым способом с явной проверкой всех потенциально опасных моментов в программе. В следующем примере реализованы простейшие функции, вычисляющие корень из числа (с проверкой неотрицательности) и деления (с проверкой деления на 0), еще одна функция вычисляет квадратный корень частного с их использованием. Нетрудно видеть, что большое количество проверкок загромождает программу и вызывает необходимость явно использовать дополнительный выходной аргумент – «статус выполнения» во всех функциях.

// Коды статуса, возвращаемые функциями

enum Status

{

  SUCCESS = 0,         // Признак успешного выполнения

  NEGATIVE_ROOT_ERROR, // Ошибка при попытке вычислить квадратный

                       // корень отрицательного аргумента

  ZERO_DIVISION_ERROR  // Ошибка при попытке деления на 0

};

// Функция вычиляет квадратный корень sqrt(val)

Status squareRoot( double val, double * result )

{

  if ( val < 0.0 )

     return NEGATIVE_ROOT_ERROR;

  * result =  std::sqrt( val );

  return SUCCESS;

}

// Функция выполняет деление a / b

Status divide( double a, double b, double * result )

{

  if ( b == 0 )

     return  NEGATIVE_ROOT_ERROR;

  * result = a / b;

  return SUCCESS;

}

// Функция вычисляет sqrt( a / b )

Status sqrtDiv( double a, double b, double * result )

{

  double d;

  Status s = divide( a, b, & d );

  if ( s != SUCCESS )

     return s;

  s = squareRoot( d, result );

  if ( s != SUCCESS )

     return s;

  return SUCCESS;

}

void main()

{

  Double result;

  Status s = sqrtDiv( 5, -1, & result );

  

  if ( s != SUCCESS )

  {

     std::cout << "Ошибка с кодом " << s << std::endl;

     return;

  }

}

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

Блок-обработчик описывается инструкцией catch(arg) (англ. поймать) с аргументом, описывающим тип перехватываемого этим блоком исключения (напоминает определение функции с одним параметром). Блоков-обработчиков может быть несколько, все они описываются последовательно сразу за блоком-инициатором проверки исключений, описываемым ключевым словом try (англ. пробовать). При возбуждении где-либо в пределах try-блока исключения, последующий список catch-блоков будет просматриваться последовательно до тех пор, пока какой-либо из них не окажется способным перехватить возбужденное исключение, в этом случае, управление передается в этот catch-блок, а аргумент catch-блока принимает значение возбужденного исключения (аналогично вызову функции с одним параметром). Если ни один из catch-блоков не способен перехватить исключение, то процесс поиска продолжится во внешнем (вызывающем) коде. Если же подходящий обработчик исключения не обнаружится вовсе, то программа будет аварийно завершена. Для перехвата всех исключений, вне зависимости от их типа, исользуется специальный универсальный блок-обработчик catch(...), который должен быть последним в списке всех блоков-обработчиков. Разумеется, в таком обработчике сам объект-исключение недоступен, поскольку неизвестен его тип. Следующий пример иллюстрирует простейшее использование обработки исключений:

  try // Попытка выполнить "опасный" участок кода

  {

 // Некоторые действия...

     throw 1; // Выбрасываем исключение

// Инструкции после throw не выполняются!

     std::cout << "Не выполняется";

  }

  catch( int e ) // перехват исключения типа int

  {

     std::cout << "Исключение типа int: " << e << std::endl;

  }

  catch( double e ) // перехват исключения типа double

  {

     std::cout << "Исключение типа double: " << e << std::endl;

  }

  catch( ... ) // перехват всех исключений

  {

     std::cout << "Исключение неизвестного типа!" << std::endl;

  }

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

// Коды ошибок (исключения)

enum ErrorCode

{

  NEGATIVE_ROOT_ERROR, // Ошибка при попытке вычислить квадратный

                       // корень отрицательного аргумента

  ZERO_DIVISION_ERROR  // Ошибка при попытке деления на 0

};

// Функция вычиляет квадратный корень sqrt(val)

double squareRoot( double val )

{

  if ( val < 0.0 )

     throw NEGATIVE_ROOT_ERROR; // Выбрасываем исключение

  return std::sqrt( val );

}

// Функция выполняет деление a / b

double divide( double a, double b )

{

  if ( b == 0 )

     throw NEGATIVE_ROOT_ERROR; // Выбрасываем исключение

  return a / b;

}

// Функция вычисляет sqrt( a / b )

double sqrtDiv( double a, double b )

{

  return squareRoot( divide( a, b ) );

}

void main()

{

  try // Попытка выполнить "опасный" участок кода

  {

     double result = sqrtDiv( 5, -1 );

  }

  catch( ErrorCode errorCode ) // перехват исключений типа ErrorCode

  {

     std::cout << "Ошибка с кодом: " << errorCode << std::endl;

  }

}


 

А также другие работы, которые могут Вас заинтересовать

22181. Структуры и стратегии поиска в пространстве состояний 360 KB
  Решение задачи методом поиска 2. Структуры и стратегии поиска в пространстве состояний 3. Решение задачи методом поиска От выбранного метода поиска то есть стратегии вывода будет зависеть порядок применения и срабатывания правил.
22182. Аппарат нечетких нейронных или гибридных сетей 450.5 KB
  Например нейронные сети хороши для задач распознавания образов но весьма неудобны для выяснения вопроса как они такое распознавание осуществляют. Они могут автоматически приобретать знания но процесс их обучения зачастую происходит достаточно медленно а анализ обученной сети весьма сложен обученная сеть обычно черный ящик для пользователя. Теоретически системы с нечеткой логикой и искусственные нейронные сети эквивалентны друг другу однако в соответствии с изложенным выше на практике у них имеются свои собственные достоинства и...
22183. Генетические алгоритмы 248.5 KB
  Это приводит к тому что приспособленность популяции возрастает позволяя ей лучше выживать в изменяющихся условиях. 1 Основные понятия генетических алгоритмов При описании генетических алгоритмов используются определения заимствованные из генетики например речь идет о популяции особей а в качестве понятий применяются ген хромосома генотип фенотип аллель. Следовательно особями популяции могут быть генотипы либо единичные хромосомы в довольно распространенном случае когда генотип состоит из одной хромосомы. Она представляет меру...
22184. Знания и их свойства. Структура и этапы разработки ЭС 193.5 KB
  Классификация знаний 3. Методология разработки интеллектуальных систем на примере СОЗ ЭС Знания и их свойства Тематика представления знаний Knowledge Representation KR уже давно считается одними из основных направлений работ в области искусственного интеллекта поскольку выбор правильного способа представления знаний является не менее значимым фактором от которого зависит успешное создание системы чем разработка самого программного обеспечения в котором используются эти знания. С тематикой представления знаний тесно связана не...
22185. Модели представления знаний 655.5 KB
  Классификация моделей представления знаний. Модели на основе теоретического подхода Классификация моделей представления знаний Одним из основных элементов в архитектуре экспертной системы является база знаний БЗ. Фейгенбаумом мощность экспертной системы зависит в первую очередь от мощности базы знаний и возможности ее пополнения.
22186. Выявление знаний от экспертов 667.5 KB
  Экспертное оценивание представляет собой процесс измерения который можно определить как процедуру сравнения объектов по выбранным показателям признакам. В качестве показателей сравнения могут использоваться пространственновременные физические психические и другие свойства и характеристики объектов. Процедура сравнения включает в себя: определение причинноследственной связи между объектами; установление степени влияния одних объектов на другие.
22187. ОБРАБОТКА ЭКСПЕРТНЫХ ОЦЕНОК 310 KB
  Групповая экспертная оценка объектов при непосредственном оценивании. В зависимости от целей экспертного оценивания и метода учета экспертных оценок возникают следующие основные задачи: построение обобщенной оценки понятий и объектов на основе индивидуальных оценок экспертов; построение обобщенной оценки на основе парного сравнения объектов каждым из экспертов; определение относительных весов взаимосвязи объектов; определение зависимостей между ранжировками; определение согласованности мнений экспертов; оценка надежности обработки...