Читаем Интернет-журнал "Домашняя лаборатория", 2007 №9 полностью

В библиотеке FCL имеются и другие классы, полезные при отладке. Класс StackTrace позволяет получить программный доступ к стеку вызовов. Класс BooieanSwitch предоставляет механизм, аналогичный константам условной компиляции. Он разрешает определять константы, используемые позже в методе условной печати WriteIf классов Debug и Trace. Мощь этого механизма в том, что константы можно менять в файле конфигурации проекта, не изменяя код проекта и не требуя его перекомпиляции.


Отладка и инструментальная среда Visual Studio.Net

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


Обработка исключительных ситуаций

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

Что делать при возникновении исключительной ситуации? Конечно, всегда есть стандартный способ — сообщить о возникшей ошибке и прервать выполнение программы. Понятно, что это приемлемо лишь для безобидных приложений; даже для компьютерных игр этот способ не годится, что уж говорить о критически важных приложениях!

В языках программирования для обработки исключительных ситуаций предлагались самые разные подходы.


Обработка исключений в языках C/C++

Для стиля программирования на языке С характерно описание методов класса как булевых функций, возвращающих true в случае нормального завершения метода и false — при возникновении исключительной ситуации. Вызов метода встраивался в If-оператор, обрабатывающий ошибку в случае неуспеха завершения метода:

bool MyMethod(…){…}

if!MyMethod(){// обработка ошибки}

{//нормальное выполнение}

Недостатки этой схемы понятны. Во-первых, мало информации о причине возникновения ошибки, поэтому либо через поля класса, либо через аргументы метода нужно передавать дополнительную информацию. Во-вторых, блок обработки встраивается в каждый вызов, что приводит к раздуванию кода.

Поэтому в C/C++ применяется схема try/catch блоков, суть которой в следующем. Участок программы, в котором может возникнуть исключительная ситуация, оформляется в виде охраняемого try-блока. Если при его выполнении возникает исключительная ситуация, то происходит прерывание выполнения try-блока с классификацией исключения. Это исключение начинает обрабатывать один из catch-блоков, соответствующий типу исключения. В C/C++ применяются две такие схемы. Одна из них — схема с возобновлением — соответствует так называемым структурным, или С-исключениям. Вторая схема — без возобновления — соответствует C++ исключениям. В первой схеме обработчик исключения — catch-блок — возвращает управление в некоторую точку try-блока. Во второй схеме управление не возвращается в try-блок.

С некоторыми синтаксическими отличиями схема с возобновлением применяется в языках VB/VBA.

Многообразие подходов к обработке исключений говорит о том, что не найден единый, удовлетворяющий всех подход. Чуть позже я расскажу о наиболее разумной, с моей точки зрения, схеме. К сожалению, в C# применяется не она.


Схема обработки исключений в C#

Язык C# наследовал схему исключений языка C++, внеся в нее свои коррективы. Рассмотрим схему подробнее и начнем с синтаксиса конструкции try-catch-finally:

try {…}

catch (т1 e1) {…}

...

catch(Tk ek) {…}

finally {…}

Перейти на страницу:

Похожие книги