ЛР2 Обработка исключений
.docЛабораторная работа №2
Тема. Обработка исключений
Раздел: Windows OS
Постановка задачи
Написать программу, демонстрирующую структурную обработку исключений. Программа должна включать:
-
локальную раскрутку (на выбор студента)
-
генерацию и обработку исключения согласно варианту задания
-
генерацию и обработку программного исключения (на выбор студента)
Программа должна представлять собой консольное приложение, написанное в среде Visual Studio или Borland C++ Builder.
Индивидуальное задание
Тип исключения соответствует типу, возвращаемому функцией DWORD GetExceptionCode(VOID).
Исключения, связанные с памятью
-
EXCEPTION_ACCESS_VIOLATION – поток попытался обратиться к виртуальному адресу, к которому у него нет доступа
-
EXCEPTION_STACK_OVERFLOW – Стек, отведенный потоку, исчерпан.
Исключения, связанные с обработкой самих исключений
-
EXCEPTION_NONCONTINUABLEEXCEPTION – фильтр исключений вернул EXCEPTION_CONTINUE_EXECUTION в ответ на не возобновляемое исключение (noncontinuable exception)
Исключения, связанные с отладкой
-
EXCEPTION_INVALID_HANDLE – в функцию передан недопустимый описатель.
Исключения, связанные с операциями над целыми числами
-
EXCEPTION_INT_DIVIDE_BY_ZERO – целочисленное деление на ноль
-
EXCEPTION_INT_OVERFLOW – переполнение разрядной сетки при операциях с целыми числами
Исключения, связанные с операциями над вещественными числами
-
EXCEPTION_FLT_DIVIDE_BY_ZERO – поток попытался сделать деление на ноль с плавающей точкой.
-
EXCEPTION_FLT_UNDERFLOW – порядок результата операции над числами с плавающей точкой меньше минимальной величины для указанного типа данных.
Теоретические сведения
При разработке больших многомодульных программ зачастую окончательную их отладку и тестирование проводят позже, чтобы не отвлекаться от логики написания программы. Но подозрительные места (в которых могут возникнуть исключительные ситуации) оформляют соответствующим образом, с возможностью реакции на возникшее исключение. Участок программы, в котором предполагается возникновения исключения, называют защищаемым блоком, а участок, где записаны действия, выполняемые в случае исключения – обработчиком.
К исключительным ситуациям относятся деление на 0 в арифметических выражениях, нарушение правил адресации, различные сбои и т.д.
Операционная система Windows предоставляет службу Structured Exception Handling (SEH), которая позволяет реагироваь на исключительные ситауции.
SEH предоставляет две возможности:
-
обработка завершений;
-
обработка исключений.
Обработчик завершения
В Microsoft Visual C++ данные блок оформляет так:
__try{
//защищаемый блок
}
__finally
{
//обработчик завершений
}
Операционная система совместно с компилятором гаратирует, что код блока finally будет выполнене независимо от того, произойдет в защищенном блоке исключение или нет. Обработка проиисходит даже при наличие в защищаемом блоке операторов goto, return, break и тому подобных.
Рассмотрим пример.
DWORD Funcenstein1()
{
DWORD dwTemp;
// действия
__try{
//защищаемый блок
//запрос разрешения на доступ к разделяемым данным
WaitForSingleObject(g_hSem, INFINITE);
g_wProtectedData=5;
dwTemp= g_wProtectedData;
return dwTemp;
}
__finally
{
//обработчик завершений
ReleaseSemaphore(g_hSem,1,NULL);
}
dwTemp=9;
retuen dwTemp;
}
В данном примере имеет место преждевременных выход из блока try (оператор return dwTemp;). Блок finally разблокирует семафор для других процессов и тем самым гаратнирует корректную работу семафора в межпроцессном взаимодействии независимо от того, как завершится защищаемый блок.
Фильтры и обработчики исключений
Обработчик исключений – это механизм, который позволяет приложениям отвечать на возможные исключительные ситуации (неправильное выполнение арифметических операций, нарушение адресации памяти).
Общий вид обработки исключений
__try{
//защищаемый блок
}
__except (фильтр исключений)
{
//обработчик исключений
}
В отличии от обрабочика завершения, блок обоаботчика исключения выполняется не всегда. Ситуация определяется значением фильтра:
-
EXCEPTION_EXECUTE_HANDLER – выполнить блок обрабочика;
-
EXCEPTION_CONTINUE_SEARCH – переход к предыдущему блоку try;
-
EXCEPTION_CONTINUE_EXECUTION – возратиться на место возникновения исключения и продолжить выполнение программы.
Для порождения исключений может быть использована функция RaiseException.
void WINAPI RaiseException(
_In_ DWORD dwExceptionCode, //код исключения
_In_ DWORD dwExceptionFlags, //флаг, задающий фильтр
_In_ DWORD nNumberOfArguments, //количество аргументов
_In_ const ULONG_PTR *lpArguments //аргументы
);
Параметры могут содержать данные приложение, необходимые для прохождения фильтра.
Содержание отчета
Отчет (печатный или рукописный) должен содержать титульную часть (номер и название лабораторной работы, номер группы и ФИО студента) и состоять из таких разделов:
-
тема работы
-
постановка задачи согласно варианту задания
-
текст программы
-
скриншоты, демонстрирующие работу программы
-
выводы
Пример программы
Далее приведен пример обработки исключений и заврешений, реализованный в среде Borland C++ Builder 6 в виде приложения с графическим интерфейсом.
#include <vcl.h>
#pragma hdrstop
#include "Main.h"
#include "Math.h"
//----------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
char* create(int type)
{
if(type==0) __asm ud2;
return "Выполнено";
}
int MyFilter(int code)
{
if (code == EXCEPTION_ILLEGAL_INSTRUCTION)//Поток выполнил недопустимую инструкцию
return EXCEPTION_EXECUTE_HANDLER; //выполним обработку в блоке except
return EXCEPTION_CONTINUE_EXECUTION; //не выполнять обработку
}
TForm1 *Form1;
//----------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//----------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
__try{
__try
{
ShowMessage(create(Edit1->Text.ToInt()));
}
__finally {
// выполняющийся в любом случае код
ShowMessage("Финальный блок выполнен!");
}
}
__except (MyFilter(GetExceptionCode()))
{
ShowMessage("Исключение сгенерировано!");
Edit1->Text=1;
}
}
//----------------------------------------------------
Контрольные вопросы
-
Что представляет собой структурная обработка исключений (structured exception handling, SEH)?
-
Для чего служит обработчик завершения (termination handler)?
-
Что представляет собой локальная раскрутка (local unwind)?
-
В каких случаях выполняется блок finally? Назвать три сценария.
-
Как и для чего используется функция BOOL AbnormalTermination(VOID)
-
Что представляют собой аппаратные и программные исключения?
-
Для чего служит обработчик исключений (exception handler)?
-
Как используются и каково назначение следующих фильтров исключений:
-
EXCEPTION_EXECUTE_HANDLER
-
EXCEPTION_CONTINUE_SEARCH
-
EXCEPTION_CONTINUE_EXECUTION
С какой инструкции возобновляет свою работу приложение после обработки исключения?
Как и для чего используются функции DWORD GetExceptionCode(VOID); LPEXCEPTION_POINTERS GetExceptionInformation(VOID);
В каком случае исключение является вложенным?
Как и для чего используется функция
VOID RaiseException(
DWORD dwExceptionCode, // 31-30:severity, 29=1:user,
// 28=0, 27-l6:facility code, 15-0
DWORD dwExceptionFlags, // 0, EXCEPTION_NONCONTINUABLE
DWORD nNumberOfArguments, // EXCEPTION_MAXIMUM_PARAMETERS
CONST DWORD *lpArguments
);
-
Как и для чего используется функция
UINT SetErrorMode(
UINT uMode // SEM_NOGPFAULTERRORBOX
);
-
Что происходит в случае возврата из Вашего фильтра необработанных исключений следующих идентификаторов:
-
EXCEPTION_EXECUTE_HANDLER
-
EXCEPTION_CONTINUE_SEARCH
-
EXCEPTION_CONTINUE_EXECUTION