- •Раздел 2. Механизмы последовательного выполнения программ
- •2.1. Классификация методов замены контекста
- •2.2. Процедуры как синхронные методы замены контекста
- •2.3. Сопрограммы
- •2.4. Примеры реализации сопрограмм в Си, в защищенном режиме процессора и в Win32
- •2.4.1. Пример реализации сопрограмм в Си
- •2.4.2. Пример реализации сопрограмм в защищенном режиме
- •2.4.3. Пример реализации сопрограмм в Win32
- •2.5. Процедуры ос
- •2.6. Прерывания как асинхронный метод замены контекста
- •2.7. Исключения
- •2.7.1. Самая общая характеристика исключений
- •2.7.2 Исключения на низком уровне
- •2.7.3. Исключения в программных средах
- •2.7.4. Обработка исключений в Delphi
- •2.7.4.1. Защита ресурсов
- •2.7.4.2. Обработка исключений
2.7.3. Исключения в программных средах
Важно отметить, что речь далее пойдет только о тех исключительных ситуациях, которые программист знает, как исправить. Если программист не знает, как исправить исключительную ситуацию (это, как правило, относится к исключениям типа GPF и ко всем исключениям низкого уровня, кроме деления на ноль), то обработку этого исключения необходимо оставить системе.
Кроме того, речь здесь пойдет о новой (относительно) концепции обработки чисто программных ошибок - обработке на уровне исключений, когда о наличии ошибки программа сигнализирует исключительной ситуацией, что повышает наглядность и структурированность программы.
Для того чтобы программа могла создавать исключительные ситуации и уметь их обрабатывать система программирования должна обладать специальными средствами, о которых речь пойдет ниже.
Такими средствами обладают языки Ада, Модула-2, Си++, среда Delphi, Java.
Дадим общую характеристику исключений с точки зрения языка высокого уровня.
При возникновении исключения нормальное выполнение программы прекращается и инициируется работа обработчика исключения. После завершения обработки исключения выполнение программы не возобновляется в точке возникновения исключения. Процесс установления связи между конкретной ошибочной ситуацией и соответствующим обработчиком называется возбуждением исключения. При возбуждении операторы, описанные в обработчике, выполняются. Сам обработчик исключений помещается в конце блока программы. Если в данном блоке не описан обработчик исключительной ситуации, то обработка исключения передается в блок, внешний по отношению к тому блоку, в котором возбуждено исключение, и т.д. Такая передача исключения называется распространением исключения. Если и в самом внешнем блоке программы отсутствует обработчик, то обработка исключения передается среде и выполнение программы в этом случае аварийно завершается.
Традиционно для проверки наличия ошибочной ситуации используются явные проверки, которые загромождают программу.
Приведем пример работы с файлом в Паскале. Последовательность работы с файлом выглядит следующим образом:
Procedure FileWork;
Begin
Открыть файл;
Прочитать данные из файла;
Записать данные в файл;
Закрыть файл;
End {FileWork};
На каждом шаге может возникнуть ошибка ввода-вывода, приводящая к аварийному завершению программы. Например, файл отсутствует или читаем данные за концом файла.
Чтобы программа не завершалась аварийно, надо отключить проверку правильности выполнения операций ввода-вывода средой Паскаля (ключ компилятора {$I-}) и после каждой операции проверять значение переменной IOResult. То есть оформлять программу следующим образом:
Procedure FileWork;
Begin
Открыть файл;
If IOResult <> 0 Then Begin
Writeln('Error!');
Exit;
End {If};
Прочитать данные из файла;
If IOResult <> 0 Then Begin
Writeln('Error!');
Exit;
End {If};
Записать данные в файл;
If IOResult <> 0 Then Begin
Writeln('Error!');
Exit;
End {If};
Закрыть файл;
If IOResult <> 0 Then Begin
Writeln('Error!');
Exit;
End {If};
End {FileWork};
После каждой операции ввода-вывода необходимо делать явные проверки. Если таких операций много, то громоздкость программы становится очевидной и наглядность резко снижена.
Обработчик исключений позволяет отделить операторы работы с файлом от операторов проверки ошибочной ситуации и скомпоновать проверки в отдельной части программы, не перемежая их с операторами, в которых могут возникать ошибки. В общем виде это будет выглядеть для нашего примера следующим образом:
Procedure FileWork;
Begin
Открыть файл;
Прочитать данные из файла;
Записать данные в файл;
Закрыть файл;
Exception :
Операторы обработки исключения, например, сообщение пользователю об ошибке;
End {FileWork};
Впервые подобный способ обработки ошибочных ситуаций был предложен в языке высокого уровня Ада и далее был распространен на более широко используемые языки. Для иллюстрации технологии обработки исключений рассмотрим принципы реализации обработки исключений в Delphi.
