Понятие механизма исключений
При работе программы могут возникать различного рода ошибки: переполнение, деление на нуль, попытка открыть несуществующий файл и т.д. Традиционно обработка ошибок осуществлялась следующим образом: в одной области кода устанавливались флаги, а во второй области выполнялась соответствующая проверка и ответные действия. Например, при попытке открытия несуществующего файла устанавливался определенный флаг, а другой участок кода проверял этот флаг и реагировал на ошибку.
Пример. Предположим, что необходимо отобразить данные в таблице на экране и эти данные хранятся в текстовом файле. Для этого может понадобиться последовательность вложенных процедур, представленная на рис. 5.1.
I-------------------- 1---------------------- 1 I---------------------------------------
' i
Рис. 5.1. Пример вложенного вызова процедур
При этомDisplayDatalnGrid вызываетRetrieveData, которая в свою очередь вызываетOpanFile, ReadFile, CloseFile.
Если произойдет какая-либо ошибка при открытии файла, то функция
OpenFile должна вернуть соответствующую информацию в функцию
RetrieveData, которая должна содержать код, блокирующий вызовы функций
ReadFile иCloseFile, а также сообщить о произошедшем в функцию
DisplayDatalnGrid, которая не должна в этом случае пытаться выводить данные в таблицу.
В современных программных системах вместо громоздкого механизма установки флагов и их обработки используется механизм исключений. Этот механизм заключается в том, что при возникновении ошибочныхситуаций
программа, написанная на Delphi, генерирует так называемоеисключение(exception) и выполнение дальнейших вычислений в данном блоке прекращается. При этом информация о возникшей исключительной ситуации будет передана в виде объекта-исключения в тот программный блок, где она произошла. Программный блок может обработать его, при этом объект-исключение автоматически уничтожается. Если в программном блоке, где произошло исключение, этого не сделать, то информация об исключительной ситуации будет передана вызывающему коду, который также прекратит дальнейшие вычисления и т.д. В конце концов, если не одна часть кода программы не обработает исключительную ситуацию, ее обработает Delphi, отобразив стандартное сообщение об ошибке.
Для того чтобы механизм исключений начал работать, необходимо просто выделить ту область программного кода, которую надо защитить от ошибок. Такой механизм предназначен для максимально возможного освобождения программиста от бремени написания процедур обработки ошибок и позволяет сконцентрироваться на других, более важных задачах.
Таким образом, можно выделить следующие главные преимущества использования механизма исключений.
· Исключения позволяют отделить код обработки ошибок от основного кода, избегая его засорения многочисленными проверками, не имеющими прямого отношения к главной цели.
· Исключения создают единый и универсальный механизм сообщений об ошибках, который используется как библиотеками Delphi, так и самой средой Delphi.
Реализация механизма обработки исключений в DelphiДля того чтобы в случае ошибки возникла исключительная ситуация, необходимо обеспечить защиту потенциально опасного участка кода. В Delphi для этих целей используются следующие ключевые слова.
. Ключевое словоtry указывает начало защищенного блока кода.
. Ключевое словоexcept указывает на конец защищенного блока кода и предшествует операторам обработки исключительных ситуаций, имеющим следующий синтаксис:
on <тиа исключительной ситуации> do <оператор>
. Ключевое словоfinally используется для указания начала блока кода, который должен исполняться всегда, даже если возникнет исключительная ситуация.
. Операторraise используется для генерации исключительной ситуации. Большинство исключительных ситуаций, которые встречаются при программировании на Delphi, генерируются системой. Однако можно самостоятельно создавать исключительные ситуации, например, при обнаружении некорректных или противоречивых данных, чтобы автоматически вызвалась процедура обработки такой ошибки.
При возникновении исключительной ситуации Delphi создает объект одного из классов исключений, определенных в системе. Все эти классы имеют общего предка - класс Exception. Иерархия классов-исключений представлена в табл. 5.1.
1а6лииа5.1 | ||||
1 № | Исключение | Описание базового класса исключений | ||
Excepion | Базовый класс все* исключений | |||
EAbort | Исключение, не выдающее сообщения. Предназначено для намеренного прерывания вычислений и быстрого выхода из глубоко вложенных процедур и функций. Генерируется процедурой Abort. | |||
EAbstractError | Попытка вызвать абстрактный метод | |||
EAccessViolation | Ошибочный доступ к памяти; например, генерируется при попытке разыменования нулевого указателя nil, попытке доступа к адресу вне памяти, распределенной приложению | |||
EArrayError | Ошибка манипулирования с потомками класса TBaseArrav: использование ошибочного индекса элемента массива, добавление слишком большого числа элементов в массив фиксированной длины, попытка вставки элемента в отсортированный массив. | |||
EAssertionFailed | Ложное выражение, проверяемое процедурой Assert | |||
EBitsError | Ошибка доступа к массиву булевых величин TBits | |||
ECacheError | Ошибка построения кэша в кубе решений. | |||
EComponentError | Ошибка регистрации или переименования компонентов | |||
EControlC | Нажатие пользователем клавиш Ctrl+C при выполнении консольного приложения. | |||
EConvertError | Ошибка преобразования строк или объектов (например, в функциях StrToInt, StrToFloat. StrToDate) | |||
П | EDatabase Error | Ошибка работы с базами данных | ||
11.1 | EDBClient | Ошибка в наборе данных клиента. Свойство ErrorCode содержит код ошибки, возвращаемый ВОЕ. | ||
11.2 | EReconcileError | Ошибка обновления данных компонента TClientDataset; свойство Context содержит информацию в виде сообщения об ошибке | ||
11.3 | EDBEngineError | Ошибка в BDE. Свойство Errors содержит информцию об ошибке - объект типа TDBErrors. Свойство ErroiCotmt хранит число ошибок. | ||
11.4 | ENoResultSet | Генерируется компонентом TQuery при попытке открыть запрос без оператора SELECT | ||
11.5 | EUpdateError | Ошибка при обновлении TProvider | ||
EDateTimeErTor | Ошибка ввода даты или времени в компоненте TDateTimePicker | |||
EDBEditError | Ошибка при попытке приложения использовать данные, не соответствующие заданной маске для поля. | |||
EDimensionMapError | Ошибка формата данных в кубе решений | |||
HDimlndexError | Ошибочный индекс в задании размерности в кубе решений | |||
E External Exception | Неизвестный код исключения | |||
ElnOutError | Ошибка ввода-вывода из файла; поле errorcode содержит информацию о конкретном виде ошибки | |||
i | EInlError | Базовый тип исключений целочисленных математических операций (см. директивы компилятора ($1-> и {$!+}) | ||
! 18.1 | EDivByZero | Попытка целочисленного деления на нуль | ||
1 18.2 | hRanRcError | Целочисленное деление или индекс вне допустимого диапазона | ||
18.3 | ElntOverflow | Переполнение в операции с целыми числами | ||
EIntfCastError | Ошибочное применение операции преобразования типов as к интерфейсу ..................................................................... | |||
ElnvalidCast | Ошибка преобразования объекта операцией as | |||
21 22 | EInvalidGraphic ElnvalidGraphicOpe- ration | Ошибочная операция с графикой | ||
ElnvalidGridOperation | Ошибочная операция с таблицей | |||
ElnvalidOperation | Ошибочная операция с компонентом; генерируется при попытке выполнить операцию, которая требует обработчика окна, над компонентом, не имеющим родителя (Parent=nil). Это исключение также генерируется при выполнении операций перетаскивания над формой (например, Forml.BeginDrag) | |||
EInvalidPointer | Ошибочная операция с указателем | |||
EListError | Ошибка работы с объектом типа списка TStringList и TList: а) при попытке сослаться на элемент с индексом вне допустимых пределов, б) попытке добавления дубликата строки в объект TStringList, в котором значение свойства Duplicates равно dupError, в) попытке вставить элемент в сортированный список, так как это может нарушить правильную последовательность элементов | |||
ELowCapacityError | Попытка выделить памяти больше, чем доступно кубу решений; надо или увеличить значение Capacity, или уменьшить размерность куба. | |||
EMathError | Базовый класс исключений операций с плавающей запятой; всегда генерируются только потомки этого исключения; обработка исключения EMathError может использоваться для перехвата всех исключений операций с плавающей запятой. | |||
28.1 | EInvalidArgument | Недопустимое значение параметра при обращении к математической функции | ||
28.2 | EInvalidOp | Неопределенная операция с плавающей запятой: процессор наталкивается на неопределенную инструкцию, ошибочную операцию или переполняется стек процессора с плавающей запятой. | ||
28.3 | EOverflow | Переполнение регистра при операции с плавающей запятой | ||
28.4 | EUnderflow | Потеря значащих разрядов при операции с плавающей запятой | ||
28.5 | EZeroDivide | Деление на нуль числа с плавающей запятой | ||
EMClDevice Error | Ошибка доступа к устройствам мультимедиа через драйвер Media Control Interface (MCI) | |||
EMenuError | Ошибка, связанная с элементами меню | |||
EOleCtrlError | Генерируется при невозможности связать приложение с компонентом ActiveX | |||
FOleError | Низкоуровневая ошибка OLE; Delphi проверяет это исключение, но не генерирует его j | |||
32.1 | EOleSysError | Ошибка OLE специфичная для интерфейса OLE IDispatch; свойство ErrorCode содержит номер ошибки | ||
32.1.1 | EOleException | Ошибка OLE, связанная с методом или свойством | ||
EOutlineError | Ошибка при работе с компонентом Outline | |||
EOutOfMemory | Неудачная попытка динамически выделить память; может генерироваться процедурой OutOfMemoryError | |||
34.1 | EOutOfResources | Генерируется при попытке приложения создать обработчик Windows, когда Windows не имеет места для размещения дополнительных разработчиков; возможно и при выделении других ресурсов Windows | ||
EPackageError | Исключение времени проектирования, генерируемое при загрузке или использовании пакета | |||
EParserError | Ошибка преобразования текста описания формы в двоичное представление, происходящая обычно из-за синтаксической ошибки исходного текста (часто из-за исправления текста вручную) | |||
E Printer | Ошибка печати; например, приложение пытается использовать принтер, которого нет, или задание по какой-то причине не может быть послано на принтер | |||
EPrivelcge | Попытка приложения выполнит ь инструкцию процессора, которая недоступна для текущего уровня привилегий | |||
EPropReadOnly | Попытка записать с помощью OLE значение свойства, которое предназначено только для чтения | |||
EPropWriteOnly | Попытка прочитать с помощью OLE значение свойства, которое предназначено только для записи | |||
EPropertyError | Ошибка при задании значения свойства | |||
ERegistry Exception | Ошибка при обращении к реестру | |||
EReportError | Ошибка задания типа сервера, из-за которой компонент Report не может соединиться с базой данных | |||
EResNotFound | Ошибка при загрузке файла ресурсов *.dfm и *.res в процессе проектирования | |||
EStackOverflow | Переполнение стека; размеры стека можно регулировать с помощью директивы {$М} | |||
EStream Error | Базочый класс исключений ошибок потоков | |||
46.1 | EFCreateError | Ошибка создания файла (недопустимое имя файла, указанный файл уже существует и не может быть перезаписан и т.д.); | ||
46.2 | EFOpenError | Ошибка открытия файла | ||
46.3 | EFilerError | Базовый класс исключений файловых потоков | ||
46.3.1 | EReadError | Невозможно прочесть заданное число байтов | ||
46.3.? | EWriteError | Невозможно записать заданное число байтов | ||
46.3.3 | EClassNotFound | Компонент не связан с приложением | ||
46.3.4 | EInvalidlmage | Невозможно прочесть файл ресурсов | ||
46.3.5 | EMethodNotFound | Невозможно найти реализацию метода | ||
EStringListError | Ошибочный доступ к окну списка с неверным индексом | |||
EThread | Конфликт в многопоточном приложении (например, вызов метода Synchronize объекта Thread до успешного завершения его предыдущего вызова) | |||
ETreeViewError | Ошибка вызова при работе с компонентом TreeView | |||
EUnsupportedType- Error | Ошибка выбора типа поля в качестве размерности куба решений | |||
EVariantError | Ошибка, связанная с типом данных variant | |||
EWin32Error | Ошибка Windows | |||