Язык программирования C++ для профессионалов

       

Особые ситуации и традиционная обработка ошибок


Наш способ обработки ошибок по многим параметрам выгодно отличается от более традиционных способов. Перечислим, что может сделать операция индексации Vector::operator[]() при обнаружении недопустимого значения индекса:

  1. завершить программу;
  2. возвратить значение, трактуемое как "ошибка";
  3. возвратить нормальное значение и оставить программу в неопределенном состоянии;
  4. вызвать функцию, заданную для реакции на такую ошибку.

Вариант [1] ("завершить программу") реализуется по умолчанию в том случае, когда особая ситуация не была перехвачена. Для большинства ошибок можно и нужно обеспечить лучшую реакцию.

Вариант [2] ("возвратить значение "ошибка"") можно реализовать не всегда, поскольку не всегда удается определить значение "ошибка". Так, в нашем примере любое целое является допустимым значением для результата операции индексации. Если можно выделить такое особое значение, то часто этот вариант все равно оказывается неудобным, поскольку проверять на это значение приходится при каждом вызове. Так можно легко удвоить размер программы. Поэтому для обнаружения всех ошибок этот вариант редко используется последовательно.

Вариант [3] ("оставить программу в неопределенном состоянии") имеет тот недостаток, что вызывавшая функция может не заметить ненормального состояния программы. Например, во многих функциях стандартной библиотеки С для сигнализации об ошибке устанавливается соответствующее значение глобальной переменной errno. Однако, в программах пользователя обычно нет достаточно последовательного контроля errno, и в результате возникают наведенные ошибки, вызванные тем, что стандартные функции возвращают не то значение. Кроме того, если в программе есть параллельные вычисления, использование одной глобальной переменной для сигнализации о разных ошибках неизбежно приведет к катастрофе.

Обработка особых ситуаций не предназначалась для тех случаев, на которые рассчитан вариант [4] ( "вызвать функцию реакции на ошибку"). Отметим, однако, что если особые ситуации не предусмотрены, то вместо функции реакции на ошибку можно как раз использовать только один из трех перечисленных вариантов. Обсуждение функций реакций и особых ситуацией будет продолжено в §9.4.3.

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

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

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

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



Содержание раздела