- •Введение
- •Выполнение работы
- •Сгенерировать исключение типа exception_continue_execution отловить его средствамиWin32, написав собственную функцию фильтра. Получить информацию об исключении.
- •Сгенерировать исключение при помощи функции RaseException
- •Использовать функции UnhandledExceptionFilter и SetExceptionFilter для необработанных исключений.
- •Обработать вложенные исключения.
- •Исследовать блок try спомощью операторов goto и __leave
Исследовать блок try спомощью операторов goto и __leave
При помощи операторов gotoиleaveвозможно покинуть блок __tryраньше времени, не дожидаясь его конца. При этом, обратим внимание, что если присутствует блокfinally, то его тело все равно выполняется, несмотря на эти операторы. Продемонстрируем это на примере:
#include <windows.h>
#include <stdio.h>
void main(INT argc, LPCWSTR argv) {
__try {
__leave; //Корректно выходим из блока
//goto e; // некорректно выходим из блока
printf("Never seen\n");
} __finally {
if (AbnormalTermination()) { // Возвращает true когда из блока try вышли корректно и false в противоположенном случае
printf("Abnort!\n");
} else {
printf("Not Abort.\n");
}
}
e:
printf("After try block\n");
system("Pause");
}
В нашем примере используется оператор leave, который завершает выполнение блокаtry. Это не аварийный вариант завершения, поэтому функцияAbnormalTermination()возвращаетfalse.
Заменим раскомментируем оператор goto:
В этом случае ход программы будет аналогичен первому случаю, но функция AbnormalTermination()возвращаетtrueтак как блокtryпрервался из-за использования оператораgoto.
Стек вызовов в обоих случаях одинаковый, поэтому я не тал его приводить.
Преобразовать структурное исключение в исключение языка С++
Для решения этой задачи воспользуемся функцией _set_se_translator, которая устанавливает пользовательский конвертер структурных С исключений. Для работы этой функции необходимо подключить библиотеку<eh.h> и в настройках проекта выставить флаг /EHа, который разрешаетC++ исключения вместе сSEHисключениями.
#include <Windows.h>
#include <iostream>
#include <eh.h>
using namespace std;
class SE_Exception //Создаем свой класс ошибки
{
private:
unsigned int nSE;
public:
SE_Exception() {} //Задаем конструктор/деструктор и функцию возвращающую поле.
SE_Exception( unsigned int n ) : nSE( n ) {}
~SE_Exception() {}
unsigned int getSeNumber() { return nSE; }
};
void MyTranslater(unsigned int i, EXCEPTION_POINTERS* pExp) { // Создаем свой транслятор
printf("In translator \n");
throw SE_Exception();
}
void CException() { // Генерируем ошибку EXCEPTION_CONTINUE_EXECUTION
int n;
__try{
RaiseException(0, EXCEPTION_NONCONTINUABLE, 0, NULL);
}
__except (GetExceptionCode()==EXCEPTION_NONCONTINUABLE_EXCEPTION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_EXECUTION){
printf("Ex_code: %X\n", GetExceptionCode() );
}
}
void main(INT argc, LPCWSTR argv) {
_se_translator_function translator;
translator = _set_se_translator(MyTranslater); // Устанавливаем в качестве транслятора, написанный нами транслятор
try {
CException();
} catch (SE_Exception) { //Ловим ошибку, но используется не дефолтный, а написанный нами транслятор.
printf("Struct exception has been caught\n");}
_set_se_translator(translator);//Возвращаем на место дефолтный транслятор
system("Pause");
}
Запустим программу.
Видим, что транслятор структурных исключений выполнен, исключение преобразовано и отловлено средствами языка С++.
Вывод
Исключения – удобный и необходимый инструмент при написании хорошего кода. Несмотря на то, что стандартные средства языка С не предусматривают исключений, APIWindowsпозволяет все-же использовать механизм исключений в С программах. Пользовательские исключения можно использовать для сообщения об ошибках и их централизованной обработки. А отлов системных исключений предотвратит экстренное некорректное завершение программы, повысив тем самым ее надежность. Даже если исключение критическое и программа не может продолжить выполняться, будет возможность завершить ее работу корректно.
Для совместимости С программ, использующих механизм исключений, с С++ программами, предусмотрена возможность преобразования структурного исключения С в исключения языка С++.
Недостаток использования механизма исключений APIWindows– непереносимость программы на другие платформы.
Санкт-Петербург
2012г