Автор работы: Пользователь скрыл имя, 20 Мая 2013 в 11:14, контрольная работа
Постановка задачи: Написать программу, демонстрирующую структурную обработку исключения EXCEPTION_INT_DIVIDE_BY_ZERO.
Для выполнения описанных выше действий в операционных системах Windows предназначен механизм структурной обработки исключений (structured exception handling, SHE). Для этого программе выделяется блок программного кода, где может произойти исключение. Этот блок кода называется фреймом, а сам код называется охраняемым кодом. После фрейма вставляется программный блок, где обрабатывается исключение.
ДНЕПРОПЕТРОВСКИЙ НАЦИОНАЛЬНЫЙ УНИВЕРСИТЕТ
ЖЕЛЕЗНОДОРОЖНОГО ТРАНСПОРТА им. В. Лазаряна
Кафедра КИТ
КОНТРОЛЬНАЯ РАБОТА
по дисциплине «Системно ПО современных систем»
выполнил студент группы 2-ПЗ Крыжановский А. Е.
принял доцент Нечай В. Я.
Днепропетровск 2012
Тема: «Обработка искючений»
Постановка задачи
Написать программу, демонстрирующую структурную обработку исключения EXCEPTION_INT_DIVIDE_BY_ZERO.
Теоретические сведения
Исключение – это событие, которое произошло во время выполнения программы, в результате совершения которого дальнейшее нормальное выполнение программы становится невозможным. Обычно такие события происходят из-за ошибок в программе или неправильных действий пользователя. После возникновения исключения требуется привести программу в рабочее состояние или выполнить её аварийное завершение с освобождением всех ресурсов, которые использовались программой.
Для выполнения описанных выше действий в операционных системах Windows предназначен механизм структурной обработки исключений (structured exception handling, SHE). Для этого программе выделяется блок программного кода, где может произойти исключение. Этот блок кода называется фреймом, а сам код называется охраняемым кодом. После фрейма вставляется программный блок, где обрабатывается исключение. Этот блок называется обработчиком исключения. Когда исключение будет обработано, управление передается первой инструкции, которая следует за обработчиком исключения.
В языке С++ для обработки исключений имеются ключевые слова __try и __except. Ключевое слово __try отмечает фрейм, а ключевое слово __except отмечает обработчик исключения. Таким образом, участок кода, где используется механизм структурной обработки исключений, выглядит так:
__try{
//Охраняемый код
}
__except (выражение-фильтр){
//Код обработки исключения
}
В операционных системах Windows существует еще один способ обработки исключений. При этом способе код, где возможно возникновение исключения, также заключается в блок __try. Но теперь за этим блоком следует блок __finally. В таком случае блок __finally выполняется всегда – независимо от того, произошло исключение или нет.
Такой способ обработки исключений называется финальная обработка исключений. Структурно финальная обработка выглядит следующим образом:
__try{
//Охраняемый код
}
__finally
{
//Финальный код
}
Финальная обработка исключений используется для того, чтобы при любом исходе исполнения блока __try освободить ресурсы (память, файлы и т.п.), которые были захвачены внутри этого блока.
Недостатком такого метода является то, что финальный код будет выполняться в любом случае. А это не всегда хорошо. Например, если мы пытаемся освободить память, которая распределяется в блоке __try, то это может привести к ошибке, если до распределения памяти дело не дошло (исключение произошло раньше). Чтобы избежать такой ситуации, нужно проверить, как завершился блок __try – нормально или нет.
Исключение EXCEPTION_ACCESS_VIOLATION возникает при попытке доступа к памяти по неправильному адресу. Неправильным считается нулевой адрес (операционная система блокирует доступ по нулевому указателю) или адрес за пределами адресного пространства процесса.
Очень важную роль в обработке исключений играет функция GetExceptionCode. С помощью нее фильтр исключения может узнать причину ошибки. Обработчик исключения должен знать, как реагировать на разные ситуации. GetExceptionCode можно вызывать между скобками оператора _except, или из обработчика исключений. Ее нельзя вызывать из функции-фильтра исключений. Например:
__try
{
}
__except
{
switch (GetExceptionCode())
{
…
}
}
В качестве фильтра исключений можно записать выражение с вызовом функции. Задача такой функции - проанализировать причину исключения, возможно, выполнить предварительную обработку, и вернуть значение, на основании которого будет выбираться обработчик исключения.
Важной особенностью функции Filter является то, что она выполняется на этапе поиска обработчика исключения. Это позволяет делать некоторые экзотические вещи. Например, эмулировать отображение файла на виртуальную память. По мере обращения по неверным указателям – будут вызываться исключения. Обработчик может выделять память, загружать в нее содержимое, а потом перезапускать программу с прерванного места. Выполнение таких действий невозможно из тела обработчика исключений.
Функция-фильтр, которая вызывается при возникновении исключения EXCEPTION_ACCESS_VIOLATION, может возвращать одно из трех значений:
- EXCEPTION_CONTINUE_EXECUTION
(–1) - исключение игнорируется и
выполнение продолжается с
- EXCEPTION_CONTINUE_SEARCH
(0) - исключение опознать не
- EXCEPTION_EXECUTE_HANDLER(1) - исключение опознано. Передача управления блоку обработки (__except) и выполнение тела блока обработки исключений.
Текст программы
#include "stdafx.h"
#include <Windows.h>
#include <iostream>
using namespace std;
DWORD exceptionFilter(DWORD exceptionCode, int &number)
{
if(exceptionCode == EXCEPTION_INT_DIVIDE_BY_ZERO)
{
cout << "Cought EXCEPTION_INT_DIVIDE_BY_ZERO\
cout << "number = " << number << "\n";
number = 10; //восстанавливаем ошибку
cout << "Continue execution.\n";
cout << "b = "<< number <<"\n";
return EXCEPTION_EXECUTE_HANDLER;
}
else
{
cout << "Didn't catch Access Violation\n";
return EXCEPTION_CONTINUE_EXECUTION;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
int a = 1000;
int b = 0;
int result;
cout << "Begin executing...\n";
__try
{
__try
{
result = a/b; //деление на ноль приводит к генерации исключения ACCESS_VIOLATION
cout << "result = " << result << "\n";
}
__finally
{
cout << "Finally. Termination: " << (AbnormalTermination() ? "\tabnormal" : "\tnormal") << endl;
}
}
__except(exceptionFilter(
{
cout << "Exception handler\n";
cout << "Value of number after handling: " << b << "\n";
}
return 0;
}
Результат работы программы
Выводы
В ходе выполнения контрольной работы, я реализовал программу, в которой существует ситуация, при которой генерируется исключение EXCEPTION_INT_DIVIDE_BY_ZERO. Функция-фильтр должна выполняет действие EXCEPTION_EXECUTE_HANDLER.