13 · Обработка ошибок
Обработка ошибок
Отказ во время выполнения — недоступный файл, недопустимый аргумент, деление на ноль — не всегда означает конец работы. Часто нужно освободить ресурс, записать сведения о случившемся и продолжить с другого шага. Для этого в языке есть три средства: оператор TRY с блоками CATCH и FINALLY, оператор ERROR, создающий отказ по прикладному условию, и встроенный тип ERROR, из которого читаются код, сообщение и место отказа.
Защищённый участок и его блоки
Оператор TRY размечает участок, отказ внутри которого программа готова обработать сама. Инструкции этого участка выполняются обычным порядком; если одна из них завершается ошибкой, остаток участка пропускается, а управление переходит в CATCH, где доступны сведения о случившемся. Блок FINALLY выполняет завершающие действия с ресурсом и срабатывает как при обычном выходе, так и при передаче ошибки дальше. Достаточно одного из двух блоков.
Речь идёт об ошибках уже запущенной программы. Ошибки лексического, синтаксического и семантического анализа обнаруживаются до запуска, поэтому TRY их не перехватывает.
Программа ниже делит на ноль внутри защищённого участка:
TRY
PRINT 10 \ 0
CATCH err
PRINT err.Code
FINALLY
PRINT "finally"
END TRY
PRINT "after"Ожидаемый вывод:
MB3001
finally
afterСтрока с делением выполнилась один раз и после обработки не повторялась, поэтому вместо числа напечатан код MB3001. Затем сработал FINALLY со своим сообщением, и только после него управление продолжилось за END TRY — так появилась третья строка after. Порядок вывода повторяет порядок работы: обработка, завершение, продолжение.
Сведения об ошибке
Строка CATCH err объявляет переменную err встроенного типа ERROR: отдельный DIM или CONST не нужен, потому что имя введено самим обработчиком. Значение переменная получает при переходе в CATCH, внутри блока доступна только для чтения, но константой CONST при этом не является. Правила объявления и области видимости собраны в статье TRY.
Тип ERROR содержит четыре поля, заранее определённых языком, поэтому объявлять их в программе не требуется. В записи err.Code имя переменной — err, точка обозначает обращение к полю, а Code — имя поля; вся запись читает значение поля. Все четыре поля доступны только для чтения. Их типы и назначение:
| Поле | Тип | Назначение |
|---|---|---|
| Code | STRING | Код системной или пользовательской ошибки. |
| Message | STRING | Английский текст системной ошибки либо исходный текст пользовательского сообщения ERROR. |
| Line | INTEGER | Номер строки исходника начиная с 1; 0, если место неизвестно. |
| Column | INTEGER | Номер столбца исходника начиная с 1; 0, если место неизвестно. |
Язык сообщений
Поле Message хранит системный текст на английском языке независимо от языка интерфейса IDE. Текст, переданный оператору ERROR явно, сохраняется без перевода. Различие между системным и прикладным сообщением разобрано в статье TRY.
Пользовательские ошибки
Когда отказ означает нарушение прикладного условия, программа создаёт его сама: ERROR с кодом и необязательным сообщением вводит новую ошибку, а ERROR со значением ошибки передаёт уже полученный отказ наружу, сохраняя исходное место. Оба случая обрабатываются тем же TRY, что и системные ошибки, а после успешной обработки программа продолжается за END TRY.
Справочные статьи
TRY, CATCH, FINALLY · ERROR · Возврат через FINALLY · Файловые отказы · Диагностика массивов