- •Введение
- •Выполнение работы
- •Сгенерировать исключение типа exception_continue_execution отловить его средствамиWin32, написав собственную функцию фильтра. Получить информацию об исключении.
- •Сгенерировать исключение при помощи функции RaseException
- •Использовать функции UnhandledExceptionFilter и SetExceptionFilter для необработанных исключений.
- •Обработать вложенные исключения.
- •Исследовать блок try спомощью операторов goto и __leave
Санкт-Петербургский государственный политехнический университет
Факультет технической кибернетики
Кафедра Компьютерные системы и программные технологии
Отчёт по лабораторной работе №3
Дисциплина: "Системное программное обеспечение"
Тема: Обработка исключений
Выполнил студент гр. 5081/13 Залеский А. А.
Преподаватель __________ Душутина Е. В.
\
Введение
Обработка исключений начинается в ядре операционной системы. Так, каждому типу исключений поставлен в соответствие свой обработчик, получающий управление в случае возникновения определённого события. Осуществив необходимые действия, ядро Windows передаёт управление потоку, в котором произошло исключение для его дальнейшей обработки. Однако, поток продолжает своё выполнение не с места возникновения исключения, а со строго определённого места - пользовательского диспетчера исключений KiUserExceptionDispatcher, располагающегося в библиотеке NTDLL.DLL. В качестве информации, необходимой для корректной обработки исключения, потоку передаётся вся необходимая информация о месте исключения и его характеристиках -- для этого, в стек потока заносятся структуры EXCEPTION_RECORD и CONTEXT, а указатели на эти структуры передаются в качестве аргументов непосредственно KiUserExceptionDispatcher.
Структура EXCEPTION_RECORD представляет собой блок информации, описывающий исключение, возникшее в ходе выполнения потока. Её формат документирован и представлен ниже.
typedef struct _EXCEPTION_RECORD {
DWORD ExceptionCode;
DWORD ExceptionFlags;
struct _EXCEPTION_RECORD *ExceptionRecord;
PVOID ExceptionAddress;
DWORD NumberParameters;
ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
} EXCEPTION_RECORD, *PEXCEPTION_RECORD;
Интересующее нас поле ExceptionFlags предназначено для определения того, является ли данное исключение продолжаемым. В случае, если это не так, будет установлен флаг EXCEPTION_NONCONTINUABLE. Попытка возобновить выполнение потока после возникновения не продолжаемого исключения приведёт к возникновению исключения с кодом EXCEPTION_NONCONTINUABLE_EXCEPTION. Его и нужно отловить.
Как следует из описания, нужно создать ошибку у которой будет установлен флаг EXCEPTION_NONCONTINUABLE, а затем попытаться продолжить её и отловить ошибку о невозможности продолжения процесса.
__try{
RaiseException(0, EXCEPTION_NONCONTINUABLE, 0, NULL);
}
__except (GetExceptionCode()==EXCEPTION_NONCONTINUABLE_EXCEPTION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_EXECUTION){
}
В блоке except проверяем, отловили ли мы ошибку EXCEPTION_NONCONTINUABLE_EXCEPTION и если отловили, выходим из блока. Иначе, пытаемся продолжить выполнение потока. Таким образом, первый раз вызывается команда EXCEPTION_CONTINUE_EXECUTION, а после повторной ошибки, вызывается EXCEPTION_EXECUTE_HANDLER.
Приведу вырезку с сайта MSDN о кодах ошибкок. У отлавливаемой нами ошибки код C0000025.
Выполнение работы
Сгенерировать исключение типа exception_continue_execution отловить его средствамиWin32, написав собственную функцию фильтра. Получить информацию об исключении.
#include <iostream>
#include <windows.h>
DWORD Filter(DWORD ExCode, LPEXCEPTION_POINTERS ExInfo){
printf("Ex_code: %X\n", ExCode );
printf("Ex_address: %X\n",ExInfo->ExceptionRecord->ExceptionAddress);
return(ExCode==EXCEPTION_NONCONTINUABLE_EXCEPTION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_EXECUTION); } //Если код исключения, пришедшего в фильтр не равен EXCEPTION_NONCONTINUABLE то пытаемся продолжить выполнение программы, иначе, выходим из фильтра.
void tmain()
{
int n;
__try{//Вызываем исключение с флагом EXCEPTION_NONCONTINUABLE
RaiseException(0, EXCEPTION_NONCONTINUABLE, 0, NULL);
}
__except (Filter(GetExceptionCode(), GetExceptionInformation())){ // Направляем обработчик в функцию фильтра
}
system("Pause");
return;
}
Результат выполнение программы: