Тверской государственный университет
Опубликован: 13.09.2006 | Доступ: свободный | Студентов: 3491 / 369 | Оценка: 4.65 / 4.29 | Длительность: 30:37:00
Специальности: Программист, Менеджер
Лекция 11:

Отладка и оптимизация программ. Отладка

Ошибки периода выполнения и их обработка

Итак, отладка программы завершена, последняя найденная ошибка исправлена. Теперь программа должна быть передана пользователю. Значит ли это, что в ходе работы пользователя с программой не будут возникать ошибки? Обязательно, будут! Нужно предпринять специальные меры, чтобы появление этих ошибок не приводило к неприятным последствиям. Если этого не сделать, то при возникновении ошибки на экране появляется сообщение, как правило, мало что говорящее пользователю и программа завершает свою работу. Как правило, все это сопровождается нелестными высказываниями пользователя в адрес разработчика. Заметьте, ошибки этого периода (run time errors) могут быть и в правильно работающей программе. Они могут возникать из-за неверных действий самого пользователя, не знающего спецификаций. Обычно ошибки связаны с вводом данных несоответствующих типов или вводом значений, выходящих за пределы допустимого диапазона. Пользователь может пытаться открыть несуществующий файл, или файл, который он необдуманно удалил. При работе пользователя, например, в Access может быть сделана попытка открытия несуществующей таблицы или формы. В общем, у пользователя есть масса возможностей нарушить спецификации, особенно, если они не четко сформулированы. Но не стоит обольщаться, многие ошибки на совести программиста. Правильно считать, что во всех случаях виноват программист. В его задачу входит обнаружение и обработка всех исключительных ситуаций, возникающих в процессе работы программы. Сейчас мы и переходим к рассмотрению самого понятия исключительной ситуации и о тех средствах, которые есть в VBA для их обработки.

Исключительная ситуация или исключение (exception) возникает при выполнении программы и делает ее дальнейшее выполнение невозможным или нецелесообразным ввиду неопределенности, непредсказуемости или неправильности дальнейшего результата вычислений. Управление исключениями (exception handling) включает специально предусмотренное обнаружение исключений, перехват управления выполнением программы при возникновении исключения и передачу этого управления специальному разделу программы - обработчику исключения.

Определения, которые мы дали, носят общий характер и применимы к любому языку программирования. Следует сказать, что стандарт на исключения, их классификацию, способы обработки, еще не сформировался. Например, в языке Visual C++ обработка исключений значительно изощренней, чем в языке VBA. Следует сказать, что в VBA, к сожалению, не используется общепринятый термин исключение, вместо него используется термин ошибка. Суть дела от этого не меняется. Давайте начнем с рассмотрения общей схемы управления ошибками (исключениями) в языке VBA.

Модель управления ошибками в языке VBA.

В языке VBA обработка ошибок сосредоточена на уровне процедуры (функции). В каждой процедуре может быть выделен один или несколько охраняемых блоков, с каждым из которых связывается свой обработчик ошибки. Если во время работы охраняемого блока возникла ошибка (исключение), то нормальный ход выполнения процедуры приостанавливается, управление ее работой перехватывается и передается обработчику ошибки. Стандартный объект Err содержит информацию об ошибке. Поэтому в обработчике ошибки имеется возможность обработать возникшую ситуацию, исправить ее, запросив, например, у пользователя дополнительные данные, и принять правильное решение о дальнейшем ходе выполнения программы. В некоторых случаях, когда устранена причина ошибки или ее последствия, управление может быть возвращено в охраняемый блок, так что вычисления будут продолжены. В некоторых случаях работа программы приостанавливается с выдачей пользователю вразумительного объяснения причин, приведших к невозможности дальнейшего выполнения программы.

Давайте разберемся, что значит "возникла ошибка"? Точнее следует говорить возбуждена (raise) ошибка. Кто обнаруживает ошибку? Обнаружение исключительной ситуации и возбуждение ошибки может быть сделано самой операционной системой (VBA) или исполняемой процедурой. Ошибки, возбуждаемые операционной системой, могут быть следствием аппаратных прерываний, например, из-за деления на ноль, вычисления корня из отрицательного числа, но это могут быть и ошибки, программно обнаруживаемые операционной системой, например, при попытке открыть несуществующий файл. Все эти ошибки будем называть системными или внутренними ошибками VBA. Все они тщательно классифицированы и каждая из них однозначно идентифицируется своим номером. Другую группу ошибок составляют собственные или пользовательские ошибки, возбуждение которых предусматривает программист. Например, при работе с объектом пользовательского класса программист может и должен предусмотреть специальную процедуру Check, которая проверяет правильность задания свойств объекта. Если обнаруживается, что свойства объекта заданы некорректно, так что выполнение операций над ним приведет к неверным результатам, то возбуждается собственная ошибка. Конечно, также как и для стандартных ошибок, ее тип должен быть полностью определен, задан ее номер и другие параметры. Возможно, программное обнаружение исключительных ситуаций и возбуждение собственных ошибок это наиболее важная и наиболее трудная часть программистской работы по управлению ошибками. Заметим, что какие бы ошибки не возбуждались, - внутренние или пользовательские, в момент возбуждения ошибки заполняются свойства объекта Err, так что он содержит всю информацию о последней возникшей ошибке.

Синтаксически охраняемый блок окружен специальными операторами On Error. В начале блока оператор On Error задает метку обработчика ошибки охраняемого блока. Обработчик ошибок, как правило, завершается специальным оператором Resume, который задает точку в процедуре, которой передается управление после завершения обработки ошибки. Приведем схему процедуры с тремя охраняемыми блоками:

Sub ProcWithErrors()
	'Первый охраняемый блок
		On Error GoTo ErrHadler1	' подключение 1-го обработчика ошибок
			' Первая часть процедуры, которая может вызвать ошибку.
			...
		On Error GoTo 0	отключение 1-го обработчика ошибок

	'Второй охраняемый блок
		On Error GoTo ErrHadler2	' подключение 2-го обработчика ошибок
			' Вторая часть процедуры, которая может вызвать ошибку.
			...
		On Error GoTo 0	отключение 2-го обработчика ошибок

	'Третий охраняемый блок
		On Error GoTo ErrHadler3	' подключение 3-го обработчика ошибок
			' Третья часть процедуры, которая может вызвать ошибку.
			...
		On Error GoTo 0	отключение 3-го обработчика ошибок

		RepeatPoint:		' точка, с которой возобновляется выполнение
			'после обработки ошибки в 3-ей части
			...

		Exit Sub		'выход из процедуры при отсутствии ошибок
		'ОбработкаОшибок:
		ErrHandler1:	
			' 1-ый обработчик ошибок
			...
			Resume	'возврат к оператору, вызвавшему ошибку в 1-ой части

		ErrHandler2:	
			' 2-ой обработчик ошибок
			...
			Resume Next	'переход к оператору, следующему за оператором 
			'вызвавшим ошибку во 2-ой части

		ErrHandler3:	
			' 3-ий обработчик ошибок
			...
			Resume RepeatPoint	'переход к строке, с которой возобновляется
			'выполнение после обработки ошибки в 3-ей части
End Sub
10.2.

Такова общая, достаточно простая схема обработки ошибок (исключений) в языке VBA. Стоит обратить внимание на то, что ситуация все же не столь проста, как может показаться с первого взгляда. Дело в том, что любой охраняемый блок может содержать вызовы процедуры процедур и функций. Поэтому реальная ситуация обычно такова, - один из операторов охраняемого блока запускает цепочку вызовов процедур и функций, каждая из которых имеет свои охраняемые блоки и свои обработчики ошибок. Ошибка может произойти на каком-то шаге в одной из вызванных процедур. Какие обработчики будут вызываться и в каком порядке, об этом поговорим чуть позже. Чтобы разобраться с деталями, вначале стоит подробно рассмотреть возможности используемых средств - операторов On Error, Resume и объекта Err с его свойствами и методами.

Оператор On Error

Имеется три варианта синтаксиса этого оператора:

On Error GoTo строка
On Error Resume Next
On Error GoTo 0

Рассмотрим подробно каждый из трех вариантов:

  1. Оператор On Error GoTo строка используется, как заголовок охраняемого блока. Его обязательный аргумент строка является либо меткой строки или номером строки, задающей начало обработчика ошибки. Заметьте, обработчик ошибки - это фрагмент кода, расположенный в той же процедуре, что и охраняемый блок. Если в охраняемом блоке возбуждается ошибка, то управление покидает охраняемый блок и передается на указанную строку, запуская, тем самым, обработчик ошибок, начинающийся в этой строке.
  2. Оператор On Error Resume Next также используется, как заголовок охраняемого блока. В этом случае с охраняемым блоком обработчик ошибок не связан. Точнее, он состоит из одного оператора Resume Next, включенного непосредственно в оператор On Error. При возникновении ошибки в охраняемом блоке, управление перехватывается и передается оператору, следующему за оператором, приведшему к ошибке. Конечно, такая ситуация разумна только в том случае, когда вслед за оператором, при выполнении которого потенциально возможна ошибка, программист помещает оператор, анализирующий объект Err, и в случае ошибки принимает меры по ее устранению. Это довольно типичная ситуация, когда обработка возможной ошибки заранее предусмотрена и встроена в процедуру.
  3. Оператор On Error GoTo 0 является закрывающей скобкой, - он завершает охраняемый блок. Выполнение оператора On Error GoTo 0 приводит также к "чистке" свойств объекта Err аналогично методу Clear этого объекта. Синтаксис оператора трудно признать удачным, фраза GoTo 0 только сбивает с толку, поскольку 0 не рассматривается как номер строки, даже если строка с номером 0 существует. Неудачным решением является и то, что этот оператор можно опускать, если охраняемый блок завершается вместе с самой процедурой. Лучше бы иметь завершающую структурную скобку, как это сделано в VBA для всех управляющих структур. В процедурах, состоящих из нескольких охраняемых блоков, применение этого оператора обязательно. Прежде чем объявить новый охраняемый блок, нужно отключить текущий оператором On Error GoTo 0.

Заметьте, если ошибка возбуждена вне охраняемого блока, то она приведет к стандартному способу ее обработки, заключающемуся в том, что будет выдано сообщение об ошибке и выполнение будет приостановлено. Взгляните, как выглядит стандартное сообщение об ошибке:

Стандартное сообщение об ошибке периода выполнения

Рис. 10.14. Стандартное сообщение об ошибке периода выполнения

Доступные кнопки в этом окне определяют возможные действия в этом случае. Все эти варианты, как правило, мало устраивают конечного пользователя. Вот еще один вариант такого сообщения:

Другой вид окна сообщения об ошибке периода выполнения

Рис. 10.15. Другой вид окна сообщения об ошибке периода выполнения
полина есенкова
полина есенкова
Дмитрий Вологжин
Дмитрий Вологжин
Добрый день, прошел тесты с 1 по 9, 10 не сдал, стал читать лекцию и всё пройденные тесты с 1 по 9 сбросились, когда захотел пересдать 10 тест.