Выбрать главу

try

readln(a,b);

writeln(mymod(a,b) mod (a-1));

...

except

on System.DivideByZeroException do

writeln('Деление на 0');

end;

Отличие от вывода внутри функции состоит в том, что при разработке программы мы сами определяем действие, которое необходимо выполнять при обработке исключения. Это может быть специфическое сообщение об ошибке, вывод в файл ошибок или пустой оператор (в случае, когда требуется беззвучно погасить исключение).

Однако, данное решение обладает существенным недостатком: исключение System.DivideByZeroException будет возбуждено и при a=1 и не будет связано с функцией mymod. Для устранения подобного недостатка определим собственный класс исключения и возбудим его в функции mymod:

type MyModErrorException = class(System.Exception) end;

function mymod(a,b: integer): integer;

begin

if b = 0 then

raise new MyModErrorException('Функция mymod: деление на 0');

Result := a - (a div b) * b;

end;

Тогда обработка ошибок будет выглядеть так:

try

readln(a,b);

writeln(mymod(a,b) mod (a-1));

...

except

on System.DivideByZeroException do

writeln('Деление на 0');

on e: MyModErrorException do

writeln(e.Message);

else writeln('какое-то другое исключение')

end;

Если сделать MyModErrorException наследником класса System.ArithmeticException, как и System.DivideByZeroException, то последний код можно упростить:

type MyModErrorException = class(System.ArithmeticException) end;

...

try

readln(a,b);

writeln(mymod(a,b) mod (a-1));

...

except

on e: System.ArithmeticException do

writeln(e.Message);

else writeln('Какое-то другое исключение')

end;

Наконец, можно поступить следующим образом. Перехватим в функции mymod исключение System.DivideByZeroException и в ответ сгенерируем новое - MyModErrorException:

function mymod(a,b: integer): integer;

begin

try

Result := a - (a div b) * b;

except

on e: System.DivideByZeroException do

raise new MyModErrorException('Функция mymod: деление на 0');

end;

end;

Стандартные классы исключений

Все классы исключений являются потомками класса System.Exception, включающего следующий интерфейс:

type

Exception = class

public

constructor Create;

constructor Create(message: string);

property Message: string; // только на чтение

property StackTrace: string; // только на чтение

end;

Свойство Message возвращает сообщение, связанное с объектом исключения.

Свойство StackTrace возвращает стек вызовов подпрограмм на момент генерации исключения.

Ниже приводятся некоторые классы исключений, определенные в пространстве имен System и являющиеся производными от класса System.SystemException:

System.OutOfMemoryException - недостаточно памяти для выполнения программы;

System.StackOverflowException - переполнение стека (как правило, при многократных вложенных вызовах подпрограмм);

System.AccessViolationException - попытка доступа к защищенной памяти;

System.ArgumentException - неверное значение параметра подпрограммы;

System.ArithmeticException - базовый класс всех арифметических исключений. Наследники:

System.DivideByZeroException - целочисленное деление на 0;

System.OverflowException - переполнение при выполнении арифметической операции или преобразования типов;

System.FormatException - неверный формат параметра (например, при преобразовании строки в число);

System.IndexOutOfRangeException - выход за границы диапазона изменения индекса массива;

System.InvalidCastException - неверное приведение типов;

System.NullReferenceException - попытка вызвать метод для нулевого объекта или разыменовать нулевой указатель;

System.IO.IOException - ошибка ввода-вывода. Наследники:

System.IO.IOException.DirectoryNotFoundException - каталог не найден;

System.IO.IOException.EndOfStreamException - попытка чтения за концом потока;

System.IO.IOException.FileNotFoundException - файл не найден.

Исключения, определяемые пользователем

Для определения своего типа исключения достаточно породить класс - наследник класса Exception:

type MyException = class(Exception) end;

Тело класса-исключения может быть пустым, но, тем не менее, новое имя для типа исключения позволит его разграничить с остальными исключениями:

try

...

except

on MyException do

writeln('Целочисленное деление на 0');

on Exception do

writeln('Файл отсутствует');

end;

Исключение может содержать дополнительную информацию, связанную с точкой, в которой произошло исключение:

type

FileNotFoundException = class(Exception)

fname: string;

constructor Create(msg,fn: string);

begin

inherited Create(msg);

fname := fn;

end;

end;

...

procedure ReadFile(fname: string);

begin

if not FileExists(fname) then

raise new FileNotFoundException('Файл не найден',fname);

end;

...

try

...

except

on e: FileNotFoundException do

writeln('Файл '+e.fname+' не найден');

end;

Повторная генерация исключения

Для повторной генерации исключения в блоке except служит оператор raise без параметров:

raise;

Например:

try

...

except

on FileNotFoundException do

begin

log.WriteLine('Файл не найден'); // запись в файл ошибок

raise;

end;

end;

Примеры обработки исключений