Лабораторные работы по информатике для специальности «Моделирование и исследование операций в организационно-технических системах»
Лабораторная работа №12 Структурированная обработка ошибок.
В лабораторной работе рассмотрен механизм обработки исключительных ситуаций, синтаксис описания защищенных блоков. Приведены примеры программ использующих защищенные блоки.
Для обработки исключительных ситуаций в Object Pascal предусмотрен механизм защищенных блоков. Защищенный блок начинается зарезервированным словом try (попытаться выполнить) и завершается словом end. В Object Pasсal существует два вида защищенных блоков: блок except (исключить) и блок finally (завершить). Каждый из видов защищенных блоков подробно рассматривается ниже.
Синтаксис этого защищенного блока имеет следующий вид try
<операторы> finally
<операторы> end;
Если при выполнении операторов в секции try finally не произошло ошибок, то далее выполняются операторы секции finally end. Если при выполнении операторов в секции try finally в каком-либо из операторов произошла ошибка, то пропускаются все операторы начиная с ошибочного и начинают выполняться операторы секции finally end. Иными словами, операторы в секции finally end выполняются всегда (рисунок 1).
Лабораторные работы по информатике для специальности «Моделирование и исследование операций в организационно-технических системах»
Рисунок 1 – Логика работы блока завершения
Защищенные блоки этого вида применяют для корректного освобождения ресурсов. Например, если при работе с файлом произошла какая-либо ошибка, то его необходимо закрыть. Если ошибок не было, то при завершении работы файл все равно надо закрыть. Модернизируем программу осуществляющую копирование файлов приведенную в лабораторной работе № 11, добавим обработку ошибок.
Листинг 1 – Копирование файлов
program CopyFile;
{$APPTYPE CONSOLE} |
|
uses SysUtils, Classes; |
|
var Srm1, |
//входной поток |
Srm2:TFileStream; |
//выходной поток |
SourceFileName, |
//имя входного файла |
DestFileName:string; //имя файла копии begin
//открываем файл источник данных write('Source file >> '); readln(SourceFileName);
try //в этом блоке может произойти ошибка
//создаем поток в режиме только для чтения
Srm1:=TFileStream.Create(SourceFileName, fmOpenRead);
//создаем файл приемник write('Destination file >> '); readln(DestFileName);
//создаем поток в режиме создания нового потока
Srm2:=TFileStream.Create(DestFileName, fmCreate);
//копирование содержимого потока Srm1 в Srm2 Srm2.CopyFrom(Srm1, Srm1.Size); writeln('File success copy');
Лабораторные работы по информатике для специальности «Моделирование и исследование операций в организационно-технических системах»
finally
//уничтожение объектов
Srm1.Free;
Srm2.Free;
end;
writeln('Press Enter to exit'); readln;
end.
Блок исключения имеет следующий синтаксис try
<операторы> except
<обработчики исключений> else
<операторы> end;
Логика работы этого блока следующая. Если при выполнении операторов секции try except не было ошибок, то операторы в секции except end пропускаются. Если при выполнении секции try except происходит ошибка, то выполнении операторов этой секции прерывается, начиная с оператора вызвавшего ошибку и начинают выполняться операторы секции except end (рисунок 2).
Рисунок 2 – Работа блока исключения
В секции except end располагаются обработчики исключений имеющие следующий синтаксис
on <класс исключения> do <оператор>;
Лабораторные работы по информатике для специальности «Моделирование и исследование операций в организационно-технических системах»
где on, do – зарезервированные слова;
<класс исключения> – класс обработки исключения.
Имя класса служит ключом выбора, а обработка исключения производится оператором стоящим после слова do. Поиск нужного обработчика осуществляется с начала списка вниз до тех пор пока не встретится класс способный обрабатывать исключение данного типа. Если подходящего класса не встретится, то управление передается операторам, стоящим за else.Если тип и причина возникновения ошибки не существенны, то можно в секции except end вообще не указывать обработчики исключений, а сразу вставить код реакции на ошибку, например
try
...
except
...
writeln(‘Fatal Error’)
...
end;
Защищенные блоки могут вкладываться друг в друга на нограниченуую глубину. Модифицируем программу приведенную в листинге 1
Листинг 2
program CopyFile2;
{$APPTYPE CONSOLE} |
|
uses SysUtils, Classes; |
|
var Srm1, |
//входной поток |
Srm2:TFileStream; |
//выходной поток |
SourceFileName, |
//имя входного файла |
DestFileName:string; //имя файла копии begin
//открываем файл источник данных write('Source file >> '); readln(SourceFileName);
try //в этом блоке может произойти ошибка try
//создаем поток в режиме только для чтения
Srm1:=TFileStream.Create(SourceFileName, fmOpenRead);
//создаем файл приемник write('Destination file >> '); readln(DestFileName);
//создаем поток в режиме создания нового потока
Srm2:=TFileStream.Create(DestFileName, fmCreate);
//копирование содержимого потока Srm1 в Srm2 Srm2.CopyFrom(Srm1, Srm1.Size); writeln('File success copy');
except
writeln('Fatal Error!'); end;
finally
//уничтожение объектов
Srm1.Free;
Srm2.Free;
Лабораторные работы по информатике для специальности «Моделирование и исследование операций в организационно-технических системах»
end;
writeln('Press Enter to exit'); readln;
end.
Для инициирования собственного исключения необходимо использовать зарезервированное слово raise (возбудить). Если это слово встретилось в секции try...exception или try...finally, немедленно начинают свою работу секции соответственно except...end и finally...end. Если оно встретилось в except...end или finally...end, считается,
что данный защищенный блок на текущем уровне вложенности (блоки могут быть вложенными) завершил свою работу и управление передается вышестоящему уровню.
Слово raise возбуждает исключение самого общего класса Exception. Если необходимо возбудить исключение конкретного типа (неважно - стандартного или собственного), необходимо явно указать класс создаваемого в этот момент объекта путем вызова его конструктора. Например, следующий оператор возбудит ошибку ввода/вывода:
raise EInOutError.Create('Ощибка!');
Обратите внимание, что после возбуждения исключительной ситуации и создания объекта для обработки исключительной ситуации, осуществляется переход на ближайший блок except end, т.е. операторы стоящие после raise … не будут выполняться.
Класс Exception
Класс Exception является родительским для всех классов исключений. Этот класс, а также многие его потомки описаны в модуле SysUtils. Класс Exception имеет несколько важных свойств и методов.
constructor Create(const Msg: String);
Создает объект исключение и помещает в него сообщение Msg. property Message: String
Содержит сообщение об ошибке.
Стандартные классы исключений
В Delphi определено много стандартных классов исключений, некоторые из них приведены в таблице 1.
Таблица 1– Стандартные классы исключений
Класс |
Родительский |
Описание |
исключения |
класс |
|
ЕAbort |
Exception |
Реализует «тихую» (без какого-либо сообщения) |
|
|
обработку любого исключения. |
ЕАbstractError |
Exception |
Программа пытается вызвать абстрактный метод. |
|
|
|