89785

Исключения С++

Лекция

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

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

Русский

2015-05-13

132.88 KB

4 чел.

Исключения С++

Содержание

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

  •   стандартные библиотеки assert и  signal
  •   исключения в С++
  •   генерация исключений throw
  •   контрольный блок try
  •   функции-обработки исключений catch
  •   стандартные функции-обработки исключений
  •   стандартные исключения при работе с динамической памятью
  •   стандартные исключения класса exception

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

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

Для предотвращения такого прерывания в С++ используются специальные приемы программирования.

Стандартная библиотека ASSERT.H

Стандартная библиотека ASSERT.H предоставляет макропроверки выражений:

assert(выражение);

Если результат выраженияложь, то выполнение программы прерывается с выводом диагностического сообщения.

Проверка не выполняется если определено макро NDEBUG.

Стандартная библиотека SIGNAL.H

Стандартная библиотека SIGNAL.H предоставляет механизм для простой обработки определяемых системой исключений:

#define SIGINT 2 /*сигнал прерывания*/

#define SIGFPE 8 /* исключение с плавающей точкой*/

#define SIGABRT 22 /*сигнал аварийного завершения*/

Такие исключения являются асинхронными и не выводят никаких сообщений.

Прототип функции raise() используют для генерации явного исключения:

raise(SIGFPE);//возбужден сигнал исключения с плавающей точкой

Подобные исключения могут обрабатываться и с помощью функции signal():

//вызов my_abrt()

signal(SIGABRT,my_abrt());

//действовать по умолчанию

signal(SIGABRT,SIG_DFL);

//игнорировать SIGFPE

signal(SIGFPE,SIG_IGN);

Пример#27. Использование SIGNAL.H

#include <signal.h>

#include <time.h>

#include <iostream.h>

#include <stdlib.h> //для exit(0)

//обработчик ИС SIGINT

void cntrl_c_handler(int sig);

inline double clk_psec()

{return static_cast<double>(clock())/CLOCKS_PER_SEC;}

int main()

{ int i=0, j;

cout<<“Считаем до J миллионов, введите j:”; cin>>j;

 j*=1000000;

 signal(SIGINT, cntrl_c_handler);

cout<<clk_psec()<<“ начальное время\n”;

 while (1){ ++i; if (i>j){

 cout<<clk_psec()<<“ конец цикла\n”;

 cout<<“ цикл исполнен ”<<j/1000000 <<“ миллионов раз”<<endl;

raise(SIGINT);//неявный вызов функции //обработчика ИС SIGINT

cout<<“\nвведите j:cin>>j;

j*=1000000; i=0;

cout<<clk_psec()<<“ начало цикла\n”;

}

}

}

//определение функции обработчика ИС SIGINT

void cntrl_c_handler(int sig)

{ char c;

 cout<<“прерывание”;

 cout<<“Введите Д для продолжения:”; cin>>c;

 if (c==‘Д’)

 signal (SIGINT, cntrl_c_handler);

else exit(0);

}

Исключения С++

Для реализации механизма обработки синхронных ИС введены следующие ключевые слова:

  •  try (контролировать)
  •  catch (ловить, перехватывать)
  •  throw (генерировать, порождать, бросать, посылать, формировать)

Генерация исключений

Конструкция вида:

throw выражение;

возбуждает исключение и передает обработку ИС в блок catch, которая и обрабатывает ее.

Конструкция без аргумента:

throw;

может использоваться внутри catch для перезапуска текущего исключения.

Генерация исключений

Выражение в throwявляется временный статический объект, существующий до тех пор, пока не будет произведен выход из обработчика исключения.

Выражение отлавливается catch, который может использовать его значение:

int i;

throw i;

catch (int n) {cerr<<n<<endl;}

Контрольные блоки

С помощью блока:

try

{операторы_контролируемого_блока}

список_обработчиков_catch

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

Обработчики

Обработчикэто функция с одним параметром, не возвращающая никакого значения:

  1.  обработчик использует значение исключения

catch {тип_исключения имя} {операторы}

  1.  обработчик не использует значение исключения. 

catch {тип_исключения} {операторы}

  1.  обработчик реагирует на любое исключение

catch {…} {операторы}

Пример #28. Использование механизма исключения в С++

#include <iostream.h>

//функция, генерирующая исключение

void compare(int k)

{ if (k%2 != 0) throw k;

else throweven”;

}

//Функция с контролем и обработкой исключений

void GG(int j)

{ try

 { try {compare(j);}

 catch (int n)

  {cout<<“\nOdd”;

//генерация исключения во внешнем блоке try

  throw;}

 catch (const char*)

  {cout<<“\nEven”;}

 }

 catch (int i){cout<<“\nResult=”<<I;}

}

//Главная часть 

int main(){GG(4); GG(7); return 0;}

Результат работы программы:

Even

Odd

Result=7

Системные функции обработки исключений

К ним относятся:

  •  terminate() –когда нет ни одного обработчика
  •  unexpected() –когда исключение отсутствует в списке
  •  abort() –вызывается по умолчанию
  •  exit()вызывается для прерывания программы

Их поведение состоит в вызове функции terminate(), которую можно переопределить, используя функцию:

set_terminate()

Вызов функции unexpected() можно переопределить с помощью функции:

set_unexpected()

Пример #29. Замена функции terminate()

#include <stdlib.h>// abort()

#include <except.h>

#include <iostream.h>

//указатель на предыдущую функцию

 void (*old_terminate)();

//новая функция обработки //неопознанного исключения

 void new_terminate()

{cout<<“\nNew”; abort();}

int main()

{//установка своей функции обработки

 old_terminate= set_terminate  (new_terminate);

//генерация исключения вне //контролирующего блока try

 throw(25);

return 0;

}

Стандартные исключения при работе с динамической памятью

Исключение типа xalloc (except.h) запускается, если оператору new не удается выделить место в свободной памяти, при этом вызывается функция, адресуемая указателем _new_handler().

Функция (new.h)

set_new_handler(my_handler) ;

позволяет назначить свою функцию my_handler для обработки такого исключения.

Пример #30. При выделении динамической памяти

#include <iostream.h>

#include <new.h> //set_new_handler()

#include <stdlib.h>//abort()

void new_new_handler()

{cerr<<“Ошибка при выделении памяти!”; abort(); }

int main()

{set_new_handler(new_new_handler);

for (int i=1;i<=1000; i++)

{cout<<n;

new char[614400]; //пытаемся выделить 60Кб

 cout<<“: Успех!”<<endl;}

 return 0;

}

Результат выполнения программы:

  1.  Из интегрированной среды Borland C++ 3.1 
  •  ошибка при n=1
  1.  Из командной строки ДОС
  •  ошибка при n=7 и физической памяти выделено 420 Кб
  1.  Откомпилированная под MS Windows компилятором  Borland C++ 4.5 в режиме EasyWin
  •  ошибка при n=257 и памяти выделено 15Мб, в том числе и виртуальная память под Windows

Стандартные исключения базового класса exception

Производный класс logic_error (логические ошибки) включает исключения:

  •  bad_cast (ошибка приведения)
  •  out_of_range (вне диапазона)
  •  bad_typeid (ошибка оператора typeid())

Производный класс runtime_error (ошибки времени выполнения) включает исключения:

  •  range_error (ошибка диапазона)
  •  overflow_error (переполнение)
  •  bad_alloc (ошибка размещения)

Пример #31. Тестирование приведения типов, использующая RTTI 

#include <iostream.h>

#include <typeinfo.h>//class __rtti typeinfo

#include <stdexception.h>//class exception

using namespace std;

class A {public:

 virtual void foo(){cout<<“in A”<<endl;}}

class B: public A 

{public:

 void foo(){cout<<“in B”<<endl;}}

// главная программа

int main()

{ try{ A a, *pa; B b, *pb;

 pa=&b;

 pb=dynamic_cast<B*>(pa);//удачно

 pb->foo();

 pa=&a;

 pb=dynamic_cast<B*>(pa);//неудачно

 pb->foo(); }

catch(bad_cast){cout<<“Bad cast\n”;}

  return 0;

}


 

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

40456. Социологическая теория марксизма 15.95 KB
  Марксистское понимание сущности человека и человеческого общества возникло в рамках целостного марксистского миропонимания, развитого К. Марксом и Ф. Энгельсом. Марксизм представляет собой совокупность теорий, относящихся ко многим областям объективной действительности.