Шаг 46 - Структурная обработка исключений - SEH

Об обработке исключительных ситуаций уже несколько раз было написано. Вот здесь: "Подробности - Исключительные ситуации", "Шаг 98 - Как используются исключения в VC и MFC", "Шаг 99 - Как обрабатывать исключения".

Это продолжение начатого описания. Аббревиатура SEH - это Structured exception handling. Этот механизм обработки исключений отличается от обработки исключений в С++. Он разработан специально для Windows и реализован в Visual C++. Естественно, как у каждого альтернативного метода у него есть свои плюсы и минусы. Помните мы говорили про исключения С++, что если они выбрасываются, то при обработке исключений SEH они возбуждаются. Так вот выбрасывание исключения всегда производится программным путем, а возбуждении исключения может быть программным или аппаратным. Когда возбуждается исключительная ситуация задается ее код, который можно рассматривать как тип фильтр может обрабатывать код, чтобы по разному организовать обработку. SEH предоставляет два механизма.

Общая идея обработки похожа. Код заключается в блок обработки __try, но в отличии от C++ обработки дальше может следовать один из двух блоков обработки, это либо __finaly либо __except блок. Естественно понятно, что к чему. Слово ФИНИШ даже школьники употребляют, так что __finaly понятно - все приехали. А вот взаимная вложенность допускается. Синтаксически это оформляется так:

#include "stdafx.h"

void main()
{
	__try
	{
	
	}
	__finally
	{
		
	}
}

Исключение может возбуждаться в теле __try, как внутри блока так и в функциях внутри его явно или неявно вызванных. Главная особенность __finally в том, что его работа не зависит от реализации блока __try, так как он обязательно должен выполниться в случае непредвиденной ситуации, закрыть файлы, освободить память и все там такое. Итак, что же может произойти внутри блока __try ???

Все OK тогда начнет выполняться __finally и первый оператор следующий за ним.

Выход за пределы __try, ну скажем с помощью Goto. Хотя сколько говорят им не пользоваться, но все равно такое возможно, есть еще и Return кстати. Ну вообщем любой ненормальный выход. Вот тут то и начнется. Управление-то отдавать нельзя, так как блок __finally все равно должен быть выполнен. Вообщем все равно будет выполнен __finally, а только потом передастся управление. Что с return ??? А просто не используйте и все, для этого есть специальный оператор __leave, который передает управление в самый конец __try блока. Смотрим пример:

#include "stdafx.h"
#include "iostream.h"

void main()
{
	__try
	{

		cout << "proccess " << endl;
	 	__leave;
     		cout << " ????" << endl;
	}
	__finally
	{
		cout << "Finish" << endl;
	}
}

Вот такой будет результат:

proccess
Finish
Press any key to continue

Мы прервали выполнение не выходя за пределы блока.

Исключение. Ну вот, а что будет, если будет исключение. Выполнится __finally за редким исключением, например, от TerminateProcess ничего не спасет, а так же некоторые функции в библиотеках на С вызывающие abort так же обойдут __finally.

Так вот теперь о грустном. При такой обработке исключительных ситуаций нельзя использовать объекты с деструкторами, а значит MFC в полном составе. Мы дальше изучим этот механизм конечно. Вывод, что этот механизм предназначен для написания драйверов и утилит где важно обрабатывать аппаратные исключения. Так же его можно использовать и с MFC, но при написании локальный участков кода не используя классы MFC.


Предыдущий Шаг | Следующий Шаг | Оглавление
Автор Каев Артем - 2.01.2001