Вход/Регистрация
Стандарты программирования на С++. 101 правило и рекомендация
вернуться

Александреску Андрей

Шрифт:

Как минимум, ваше приложение должно обеспечить наличие заглушек

catch(...)
в перечисленных ниже местах, большинство из которых непосредственно связаны с модулями.

• Вокруг

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

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

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

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

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

Убедитесь, что каждый модуль согласованно использует одну и ту же внутреннюю стратегию обработки ошибок (предпочтительно — исключения С++; см. рекомендацию 72) и единую стратегию обработки ошибок в интерфейсе (например, коды ошибок для API на языке С); обе эти стратегии могут быть одинаковы, но обычно это не так. Стратегии обработки ошибок могут изменяться только на границах модуля. Определите, как происходит связывание стратегий между модулями (например, как происходит взаимодействие с COM или CORBA, или что всегда следует перехватывать исключения на границе с API на языке С). Хорошим решением будет определить центральные функции, которые выполняют преобразования между исключениями и кодами ошибок, возвращаемых подсистемой. Так вы сможете легко транслировать входящие ошибки от других модулей в используемые внутренние исключения и тем самым упростить интеграцию.

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

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

catch(...)
может перехватить больше исключений, чем вы ожидаете, так что ваша программа может оказаться в неопределенной ситуации при выполнении перехвата
catch(...)
. Обратитесь к документации по вашей системе и либо приготовьтесь к обработке таких низкоуровневых исключений наиболее разумным способом, который сможете придумать, либо используйте в начале вашего приложения соответствующие системные вызовы для отключения такого поведения. Замена
catch(...)
последовательностью перехватов
catch(E1&){/*...*/} catch(E2&){/*.. .*/} ... catch(En&){/*...*/}
для всех известных типов базовых исключений
Ei
масштабируемым решением не является, поскольку вам придется обновлять этот список при добавлении новых библиотек (использующих собственные иерархии исключении) в ваше приложение.

Использование

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

Ссылки

[Stroustrup00] §3.7.2, §14.7 • [Sutter00] §8-17 • [Sutter02] §17-23 • [Sutter04] §11-13

63. Используйте достаточно переносимые типы в интерфейсах модулей

Резюме

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

Обсуждение

Чем более широко распространяется ваша библиотека, тем меньше ваш контроль над средами программирования, используемыми вашими клиентами, и тем меньше множество типов, которые ваша библиотека может надежно использовать в своем внешнем интерфейсе. Взаимодействие между модулями включает обмен бинарными данными. Увы, С++ не определяет стандартные бинарные интерфейсы; широко распространенные библиотеки для взаимодействия со внешним миром могут полагаться на такие встроенные типы, как

int
и
char
. Даже один и тот же тип на одном и том же компиляторе может оказаться бинарно несовместимым при компиляции с разными опциями.

  • Читать дальше
  • 1
  • ...
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: