Читаем Стандарты программирования на С++ полностью

Однако в большинстве функций могут произойти сбои. Если ошибка возможна, наиболее безопасным будет гарантировать транзакционное поведение функции: либо функция выполняется успешно и программа переходит из начального корректного состояния в корректное целевое состояние, либо — в случае сбоя — программа остается в том же состоянии, в котором находилась перед вызовом функции, т.е. видимые состояния всех объектов после сбойного вызова оказываются теми же, что и до него (например, значение глобальной целой переменной не может измениться с 42 на 43), и любое действие, которое вызывающий код мог предпринять до сбойного вызова, должно остаться возможным (с тем же смыслом) и после сбойного вызова (например, ни один итератор контейнера не должен стать недействительным; применение оператора ++ к упомянутой глобальной целой переменной даст значение 43, а не 44). Такая гарантия безопасности называется строгой.

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

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

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

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

Остерегайтесь оператора копирующего присваивания, которому для корректной работы требуется проверка, не выполняется ли присваивание объекта самому себе. Безопасный в отношении ошибок оператор копирующего присваивания автоматически безопасен и в плане присваивания самому себе. Использовать проверку присваивания самому себе можно только в качестве оптимизации, для того чтобы избежать излишней работы (см. рекомендацию 55).

Примеры

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

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

Пример 3. std::vector::insert. Поскольку внутреннее представление vector использует непрерывный блок памяти, вставка элемента в средину требует перемещения ряда имеющихся значений на одну позицию для освобождения места для вставляемого элемента. Перемещение выполняется с использованием копирующего конструктора T::T(const T&) и оператора присваивания T::operator=, и если одна из этих операций может сбоить (генерировать исключение), то единственный способ обеспечить строгую гарантию — это сделать полную копию контейнера, выполнить операцию над копией, а затем обменять оригинал и копию с использованием бессбойной функции vector::swap.

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

Все книги серии C++ In-Depth

Стандарты программирования на С++
Стандарты программирования на С++

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

Андрей Александреску , Герб Саттер

Программирование, программы, базы данных

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

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных