
В файле vect3.H
const int SIGHEAP = SIGUSR1;
const int SIGSIZE = SIGUSR2;
vect : : vect (int n)
{
if (n < = 0) {
raise (SIGSIZE);
cout << “\nвведите n, размер вектора:”;
cin >> n; // повтор с пользовательским значением
}
p = new int [n];
if (p = = 0) {
raise (SIGHEAP);
p = new int [n];
}
}
Теперь можно определить обработчики, которые смогут выполнять надлежащие действия. Например:
void vect_size_handler (int sig)
{
char c;
cout << “\nНеверный размер\nВведите Д для продолжения”
<<”с другим размером:”;
cin >> c;
if (c = = ‘Д’) {
signal (SIGSIZE, vect_size_handler);
}
else
exit(0);
void vect_heap_handler (int sig)
{
//Возможные действия по высвобождению памяти для кучи
//или безопасный выход
………
}
Сравним эту сложную технику со стандартной техникой обработки переполнения кучи, использующей механизм set_new_ handler(), описанный в разделе 7.12, «Перегрузка new и delete», на стр.215.
Отметьте, что и сигнал, и проверку утверждения часто можно заменить локальной проверкой и вызовом функции, что обладает большой гибкостью. Однако сигналы и проверка утверждений обеспечивают унифицированную методику. Кроме того, они удерживают от попыток сделать программу слишком уж отказоустойчивой. Во многих случаях излишнее рвение в создании такой программы есть неправильное программирование и дурная привычка. Проверка утверждений выясняет, выполнены ли согласованные условия. Сигналы и обработчики создают глобальный контекст восстановления на случай нежелательных обстоятельств. Сигналы ограничены набором асинхронных системно-зависимых условий. Однако эта схема легко расширяется с помощью введения глобальных данных, которые переустанавливаются, когда возникает условие для возбуждения исключения (raise).
Исключения С++
С++ предлагает чувствительный к контексту механизм обработки исключений. Он не предназначен для обработки асинхронных исключений, определенных в файле signal.h, таких как SIGFPE (исключение с плавающей точкой). Контекстом для возбуждения исключения является блок try (пробный блок1). Обработчики, объявленные ключевым словом catch (перехватчик), находятся ниже блока try.
В коде на С++ исключение может возбуждаться в блоке try с помощью выражения throw (запустить). Исключение обслуживается вызовом соответствующего обработчика, выбранного из списка, который идет сразу за блоком try. Ниже приведен пример:
В фале vect4.H
vect : : vect (int n) : size (n)
{
if (n < 1) //проверка предусловия
throw (n);
p = new int [n];
if (p = = 0) //проверка постусловия
throw (“СВОБОДНАЯ ПАМЯТЬ ИСЧЕРПАНА”);
}
void g ()
{
try {
vect a (n), b (n);
}
catch (int n){…..} // отлавливает неверный размер
catch (char error) {…..} // отлавливает отсутствие
// свободной памяти
}
Первый throw () имеет целый аргумент и соответствует сигнатуре catch(int n). Этот обработчик должен выполнить действия, необходимые, когда конструктору в качестве аргумента передается некорректный размер массива. Например, вывести сообщение об ошибке и прервать программу. Второй throw () получает в качестве аргумента указатель на символ и соответствует сигнатуре catch (char error).