Генерация программных исключений выполняется API-функцией Windows под названием RaisException().Ee мы рассматривать не будем — подробное изучение SEH в нашу задачу не входит. Однако на одном моменте нужно остановиться. Чем хорош механизм SEH, так это возможностью «отлавливать» аппаратные исключения и точно их идентифицировать, естественно, с помощью API-функции:
DWORD GetExceptCodeO :
Функция возвращает идентификатор типа исключения, которые определены в файле WinBase.h. Но подключать надо заголовок <wi ndows. h>. В табл. 7.1 представлены некоторые из этих идентификаторов.
Таблица 7.1. Аппаратные исключения
Значение Описание
EXCEPTION, _ACCESS_VIOLATION Попытка обратиться к «чужой» памяти
EXCEPTION, FLTDIVIDEBYZERO Деление на нуль дробных чисел
EXCEPTION, FLTOVERFLOW Переполнение для дробных чисел
EXCEPTION, _int_DIVIDE_BY_ZERO Деление на нуль для целых чисел
EXCEPTION, _int_OVERFLOW Переполнение для целых чисел
EXCEPTION _STACK_OVERFLOW Переполнение стека
В составе Windows API реализованы и другие функции, используемые в SEH. Останавливаться подробно мы на них не будем, так как это не входит в нашу задачу. В справочной системе Visual C++.NET 2003 можно найти пример, который с некоторыми модификациями представлен в листинге 7.19.
Листинг 7.19. Структурная обработка исключений
// exceptions_try_except_Statement.срр // Пример try-except и try-finally #include <iostream>
#include <windows.h> // для EXCEPTION_ACCESS_VIOLATION using std::cout; using std::endl; // функция-фильтр
int filter(unsigned int code, struct _EXCEPTION_POintERS *ep) { cout<<"in filter."<< endl; if (code == EXCEPTION_ACCESS_VIOLATION) { cout<<"caught AV as expected."<<endl; return EXCEPTION_EXECUTE_HANDLER; •// если авария
}
else {
cout<<"didn't catch AV, unexpected."<< endl;
return EXCEPTION_CONTINUE_SEARCH; // если нет аварии
};
}
int main()
{ int* p = 0x00000000; // специапьно нулевой указатель
cout<<"hello"<< endl; _try{
cout<<"in try 1"<< endl; _try{
cout<<"in try 2"<< endl;
*p = 13; // access violation
}_finally{
cout<<"in finally, termination: "<< endl;
cout<<(AbnormalTermination() ? "Uabnormal" : H\tnormalH)<< endl;
}
}_except(filter(GetExceptionCodeO, GetExceptionlnformation())){ cout<<"in except"<< endl;
}
cout<<"world"<< endl;
}
Программа специально содержит ошибку (нулевой указатель), чтобы показать обработку возникающего исключения по нарушению доступа к памяти (access violation). Демонстрируется также обязательное выполнение финального блока, несмотря на исключение. Программа выводит на экран следующее:
hello in try 1 in try 2 in filter.
caught AV as expected, in finally, termination:
abnormal in except world
Механизм SEH очень подробно описан в [46].
Резюме
Механизм обработки исключений — это объектно-ориентированный механизм обработки ошибок, возникающих при неправильной работе программ. Этот механизм был добавлен в С++, в первую очередь, в связи с необходимостью как-то реагировать на некорректное поведение программы во время работы конструкторов и перегруженных операций.
В языке С++ исключения являются объектами любого допустимого типа. В стандартной библиотеке определен ряд стандартных исключений, которые можно использовать в своей программе. Можно определить собственные типы исключений с помощью классов. Программа может генерировать (порождать) объект-исключение, контролировать возникновение исключения, перехватывать и обрабатывать его. Если исключение не перехватывается программой, то система предоставляет стандартный механизм обработки, выполняющий аварийное завершение программы.
Исключение может быть сгенерировано в одном месте программы, а обработано совершенно в другом. Если в процессе поиска подходящего блока обработки потребуется выйти из вложенных вызовов функций, то выполняется «раскрутка» стека, в процессе которой осуществляется корректный вызов деструкторов для всех локальных объектов.
Программистам часто необходимо сделать небольшую локальную сеть, для этого хорошо подойдет домашний маршрутизатор.
В заголовке функции может быть задана спецификация исключений. Если функция генерирует исключение, отличающееся от указанных в спецификации, то по стандарту должно быть инициировано аварийное завершение программы. Программе разрешается вместо стандартных установить собственные функции обработки неперехваченных исключений и аварийного завершения программы. |