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;

  }

}


 

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

21433. ОСНОВАНИЕ ВОЗНИКНОВЕНИЯ ОБЯЗАТЕЛЬСТВА 19.72 KB
  В условиях рыночной экономике действует закон стоимости в соответствии, с которым и осуществляется товарооборот в обществе. Наиболее адекватной правовой формой данного товарооборота является сделка
21434. СОДЕРЖАНИЕ ДОГОВОРА 33.46 KB
  Существенные: такие условия, которые необходимы и достаточны для заключения договора т.е. если не согласовано хотя бы одно из существенных условий договор считается незаключенным; пункт 1 статья 432 ГК: условия о предмете договора, такие условия
21435. ПЕРЕМЕНА ЛИЦ В ОБЯЗАТЕЛЬСТВЕ 20.2 KB
  Поэтому цессия всегда совершается уже воисполнение существующего обязательства В большинстве обязательств сторона имеет права и обязанности Уступка права является одновременно и переводом долга т. связано с переменой лиц а так ее не произойдет Пункт 5 письма: возможна если предмет обязательства делим Уступка права требования по возврату средств по кредитному договору: статья812 ГК: может давать только банк или другая кредитная организация т. по требованию кредитора исполняется обязательство Пассивная...
21436. ПРЕДМЕТ ИСПОЛНЕНИЯ ОБЯЗАТЕЛЬСТВА 21.06 KB
  Особые требования предъявляются к денежным обязательствам Статья 317 ГК: они д. оплачено в рублях за исключением установленными ЦБ РФ Особо важно учитывать инфляционные процессы в тех случаях когда они направлены на содержание гражданина Статья 318 ГК: сумма выплачиваемая по ДО непосредственно на содержание гражданина возмещение вреда по договору пожизненного содержания индексируется по уровню инфляции в порядке и...
21437. ГРАЖДАНСКО-ПРАВОВАЯ ОТВЕТСТВЕННОСТЬ 22.54 KB
  В результате совершенного правонарушения должны наступать такие отрицательные последствия на правонарушителя которые в дальнейшем способны предотвращать правонарушения; в качестве таких отрицательных последствий могут выступать либо лишения личного характера арест либо лишения имущественного характера конфискация неустойка штраф возмещение убытков ЮО это последствия совершенного правонарушения которое выражается в нежелательных для правонарушителя лишений личного...
21438. ТЕОРИЯ ПРИЧИННОЙ СВЯЗИ 16.29 KB
  Частный интерес потерпевшего в ГП состоит не в том чтобы подвергнуть нарушителя лишениям личностного характера а чтобы восполнить потери которые он понес ГПО это всегда ответственность одного субъекта ГП перед другим субъектом ГП этим отличается от АПО Черта обусловлена тем что ГП регулирует оо в целях удовлетворения частных интересов участников этих отношений а частные интересы участников...
21439. ВИНА 20.36 KB
  Вина имеет место тогда когда из поведения лица видно что это лицо либо желало совершить правонарушение либо не проявило ту степень заботливости и осмотрительности которое требовалось от него по характеру обязательства и условиям оборота для предотвращения правонарушения Иной подход к понятию вины: Вина никакого отношения к психическим процессам не имеет Суханов Ветрянский: вина должника имеет место тогда когда он не исполняет...
21440. Понятие об устойчивости решений дифференциальных уравнений 673 KB
  Исследование на устойчивость некоторого решения Системы уравнений 1 может быть сведено к исследованию на устойчивость тривиального решения точки покоя расположенной в начале координат. расположенной в начале координат точки покоя системы уравнений. Сформулируем условия устойчивости в применении к точке покоя . Точка покоя системы 5 устойчива в смысле Ляпунова если для каждого  можно подобрать  такое что из...
21441. Замечания по поводу классификации точек покоя 340.5 KB
  Следовательно при достаточно большом t точки траекторий начальные значения которых находятся в любой окрестности начала координат попадают в сколь угодно малую окрестность начала координат а при неограниченно приближаются к началу координат т. точки расположенные в начальный момент в окрестности начала координат при возрастании t покидают любую заданную окрестность начала координат т. Если существует дифференцируемая функция называемая функцией Ляпунова удовлетворяющая в окрестности начала координат условиям: 1 причем...