Механизм исключений |
Механизм исключений помогает прикладным программистам надежнее обрабатывать ошибочные ситуации, в том числе:
ошибки, связанные с базой данных;
прикладные ошибки;
прерывания процесса выполнения, например, при визуализации или при отказе от ввода параметров.
Программист имеет возможность обработать возникшее исключение и ликвидировать ошибочную ситуацию.
Для обработки исключения используется оператор _try. Операторы, выполнение которых может вызвать исключение, помещаются в try-блок. При возникновении исключения управление передается в блок обработки исключений и в нем выполняется on-блок, соответствующий типу возникшего исключения.
Если исключение возникло в операторе присваивания, то после выполнения on-блока элементу, стоящему в левой части оператора присваивания, присваивается значение по умолчанию (ноль для чисел, пустая строка для строк).
Затем для обработанных исключений выполняется finally-блок и операторы, следующие за оператором _try. См. пример в конце раздела.
Если для исключения не нашлось соответствующего on-блока или в on-блоке выполнился оператор _reRaise, исключение считается необработанным. Необработанные исключения вызывают прерывания нормального выполнения текущего try-блока, выполнение finally-блока и передачу управления вверх по стеку вызовов функций.
Каждый интерфейс считается помещенным в try-блок по умолчанию. Другими словами, если исключение возникает в операторах, не помещенных в try-блок, то выполняется блок обработки исключений по умолчанию. По некоторым типам исключений он просто закрывает интерфейс.
Имеется возможность продолжить выполнение с точки возникновения исключения, вызвав оператор _retry из except-блока.
Допустима обработка вложенных исключений. При этом исключения, возникшие в except-блоке или finally-блоке, передаются в except-блок внешнего обработчика. Там они могут быть обработаны или переданы дальше операторами _retry или _reRaise.
Перед выходом из оператора _try выполняется finally-блок. Чтобы его обойти применяется оператор _skipFinally.
Оператор _doFinally передает управление из try-блока или except-блока непосредственно в finally-блок.
Для создания блока, защищенного от прерывания его выполнения любыми исключениями, используется noexcept-блок (оператор _noExcept). Фактически, это try-блок без обработки исключений, в котором заблокирована выдача исключений.
Исключения идентифицируются по типу и группе. Например, все исключения работы с файлами находятся в группе ExFile. При создании except-блока имеется возможность отлавливать исключения по типу или по группе.
Прикладной программист имеет возможность описывать свои типы и группы исключений декларацией exception.
Начиная с Атлантис 5.1.12 расширен механизм объявления типов и групп исключений:
допускается объявление исключений и групп на уровне файлов и проектов;
на идентификаторы исключений распространяются общие правила видимости идентификаторов;
возможно использование исключений базового объекта в объекте-потомке при условии сохранения символьной информации для докомпиляции и наследования.
Для описания пользовательских исключений, которые не выдают сообщений, если их не обработать, введен флаг noMessage в операторе exception.
Имеется оператор _raise для создания исключений любого типа прикладным программистом. Созданное исключение обрабатывается полностью также как и системное.
Для выдачи диагностики существует функция ExploreException, возвращающая строку с сообщением.
В данном примере выдается следующая последовательность сообщений:
"Блок _try: d1(10) = 10.00".
"on-блок ExNumberConvert: Ошибка приведения string к double!!!".
"on-блок ExNumberConvert: d1 = 99.00".
"Блок _finally: d1= 0.00" - значение по умолчанию, а не присвоенное в on-блоке.
"Итого: d1(Hello) = 77.00" - значение, присвоенное блоке _finally.
//========================================================= interface aTryTest 'test' escclose; //--------------------------------------------------------- create view var d1 : double; ; //------------------------------------------------------------------------- screen WinButton; noTableNavigation; << Тест исключений прошел >> end; //--------------------------------------------------------- handleEvent cmInit: { d1 := 10; _try { Message('Блок _try: d1(10) = ' + d1); d1 := Double('Hello'); Message('Блок _try: d1(Hello) = ' + d1); } _except on ExNumberConvert: { Message('on-блок ExNumberConvert: Ошибка приведения string к double!!!'); d1 := 99; Message('on-блок ExNumberConvert: d1 = ' + d1); } else { Message ('Блок else: d1=' + d1 + ExploreException, mfError); d1 := 88; } _finally { Message ('Блок _finally: d1=' + d1); d1 := 77; } Message('Итого: d1(Hello) = ' + d1); } end // handleEvent end.
Начиная с Атлантис 5.1.12 расширен механизм объявления типов и групп исключений.