Структурная обработка исключений.

Структурная обработка исключений позволяет при возникновении ошибки в программе, обработать эту ошибку и продолжить выполнение программы. Язык программирования С++ позволяет проводить такую обработку с помощью блоков try и catch. Это весьма гибкий механизм обработки исключительных ситуаций.
Его описание можно найти в любой книге по С++. Microsoft помимо стандартного обработчика исключительных ситуаций С++ заложила в свой компилятор еще один механизм обработки завершения исключений. Это пара блоков:
__try                 __try                             
__finale             __except

Первый блок предназначен для обработки завершающего блока, а второй для обработки исключений.
В блоке __try производится стандартное выполнение программы. Блок __finaly выполняется всегда после блока __try. Блок __except выполняется при возникновении исключения. Любое количество блоков __try может быть вложено один в другой.
Однако каждый должен завершаться либо блоком finaly либо блоков except.
__try {
                   if (bNeedtoOut)
                   __leave;
                   return;
}
__finaly {
                   if (AbnormalTermination()) {}
                   else {}
}

__try {
                   //защищенный блок}
__except (
                   //фильтр исключений)
{
//обработка исключений
}
Фильтр исключений – это 1 оператор. Результатом работы этого оператора могут быть три значения 1, 0, -1.
1.        1 –  EXCEPTION_EXECUTE_HANDLER
ошибка распознана. Последствия ошибки будут ликвидированы в блоке except. Затем программа перейдет на оператор, следующий за блоком except.
2.        0 –  EXCEPTION_CONTINUE_SEARCH
Ошибка не распознана. Необходимо перейти на следующий вверх блок except.
3.        -1 – EXCEPTION_CONTINUE_EXECUTION
Ошибка распознана и устранена. Необходимо вернуться на ту же самую машинную команду, которая вызвала ошибку.

__try {
                   __try {}
                                       __except(0) {}
                   }
__except (1) {}
Если такого обработчика нет, то вызвать стандартный обработчик исключений ОС, который аварийно завершит программу.

Стек обработчиков исключений для каждой нити свой. Текущий обработчик исключений находится по адресу fs:0 (сегментный регистр). В ОС Windows сегментный регистр fs не указывает на общее адресное пространство процессов. Он указывает на небольшой блок памяти, выделяемый ОС отдельно для каждой нити. Этот блок называется Tread Environment Block (TEB) и он не документирован.  По адресу 0 в этом блоке лежит адрес текущего обработчика исключений, который, в свою очередь, уже относится к адресному пространству процесса.
 При входе в блок try{} предыдущее обращение к адресу обработчика запоминается в стеке нити и на его место записывается новое значение (адрес блока try{}). Посмотреть параметры исключения можно внутри фильтра исключений EXCEPTION_POINTER.
GetExceptionInformation ();

typedef struct {
                   PEXCEPTION_RECORD ExceptionRecord;
                   PCONTEXT ContextRecord;
} EXCEPTION_POINTER;

typedef struct _EXCEPTION_RECORD{
                   DWORD ExceptionCode;
                   DWORD ExceptionFlags;
                   struct _EXCEPTION_RECORD* ExceptionRecord;
                   PVOID ExceptionAddress;
                   DWORD NumberParametrs;
                   ULOG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETRS];
} EXEPTION_RECORD, *PEXCEPTION_RECORD;

ContextRecordсодержимое контекста регистров ЦП при исключении, который использовала данная нить.
Исключение можно вызвать намеренно. Для этого существует функция RaiseException:
PVOID  RaiseException(
                   DWORD ExceptionCode,
                   DWORD ExceptionFlags,
                   DWORD NumberOfArguments,
                   conts ULONG_PTR* lpArguments
);

Комментариев нет:

Отправить комментарий