Исключения (exception) – реакция вычислительной системы на некоторую особую ситуацию, возникшую при работе приложения. Чаще всего такие особые ситуации связаны с возникновением в исполняемом коде программы какой-либо ошибки – обращение к несуществующему файлу, неправильная работа с адресным указателем, несоответствие типов данных и т.д. В любом случае программа не может дальше выполняться и аварийно завершается с выводом некоторого кода ошибки. Любая программа, претендующая на роль современной, должна уметь перехватывать такие ситуации и, по возможности, обрабатывать их тем или иным способом. Для этого обычно в программу вставляется большое число проверок разных условий, что делает логику программы достаточно запутанной. Механизм исключений позволяет упростить обработку особых ситуаций, выделив в программе специальные блоки - обработчики исключений.
Все основные современные операционные системы и языки программирования поддерживают централизованную обработку исключений, которая строится на объектных принципах. Это означает, что для каждого подобного исключения автоматически создается объект соответствующего класса. Для этого все типичные ошибки времени выполнения классифицированы на несколько десятков классов. В языках Delphi Pascal и Java базовые библиотеки классов содержат специальную подиерархию классов, которые описывают наиболее типичные ошибки. Например, в библиотеке VCL родоначальником этой иерархии является класс Exception. Этот класс содержит около десяти различных конструкторов, которые используются при создании объекта-исключения. Каждый созданный объект несет информацию о возникшей особой ситуации.
От класса Exception порождаются дочерние подклассы для различных типов ошибочных ситуаций, например:
· EInOutError – ошибки при выполнении операций ввода или вывода;
· EIntError – ошибки целочисленной арифметики;
· EMathError – ошибки при обработке вещественных чисел;
· EConvertError – ошибки преобразования типов;
· EAccessViolation – ошибки, связанные с неправильным использованием памяти.
Эти классы, в свою очередь, могут быть родителями для более конкретных классов, например – EDivByZero (целочисленное деление на ноль). Знание иерархии классов исключений очень важно для грамотного применения данного механизма.
Для объектной обработки исключений, прежде всего в исходном тексте, необходимо найти те операторы, которые потенциально могут быть источниками таких ошибок. Эти операторы могут идти последовательно друг за другом либо могут быть разбросаны по всему исходному коду. Такие операторы можно назвать критическимилизащищеннымкодом. Начало критического кода обозначается специальной директивой try, за которой идет один или несколько критических операторов. После них размещается специальный блок обработки исключений. Начало этого блока обозначается директивой except в языке программирования Delphi Pascal и директивой catch в Java. Общий вид критического кода выглядит следующим образом:
Try
критический оператор(ы)
Except
обработчики исключений
end;
Защищенный код работает следующим образом. Если при его выполнении исключения не возникают, то блок except не выполняется, а управление передается операторам, следующим за директивой end. Если же в защищенном коде возникает исключение, то оставшиеся операторы защищенного кода не выполняются, а управление сразу передается на блок обработки.
Простейшая обработка может включать лишь вывод информационного сообщения. При необходимости можно выполнить более тщательный анализ возникшей ошибки, в частности, если в защищенный код входит несколько операторов разных типов, в блоке обработки можно предусмотреть обработку каждого из возможных типов ошибок:
Except
on EIntError do …;
on EInOutError do …;
on ИмяКласса do …;
end;
В этом блоке важным является порядок следования обработчиков. Если необходимо перехватить более конкретную ошибку, то в списке ее необходимо указать раньше, чем общий класс.
Если в защищенном коде возникает ошибка, обработчик которой не предусмотрен в блоке except, то автоматически вызывается обработчик по умолчанию, который выводит общее сообщение и аварийно завершает работу. Как только возникшее исключение обработано в блоке except, соответствующий объект автоматически уничтожается.
Кроме стандартного блока try-except-end, довольно часто используется другая разновидность: