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

[Stroustrup00] §9.2.1 • [Sutter02] §39-40

<p>60. Избегайте выделения и освобождения памяти в разных модулях</p>Резюме

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

Обсуждение

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

Следовательно, о функции освобождения памяти (т.е. операторе ::operator delete или функции std::free) при пересечении границ модулей практически нельзя строить какие-либо предположения, в особенности при пересечении границ модулей, при котором вы не можете гарантировать, что они будут скомпилированы одним и тем же компилятором С++ с одними и теми же опциями. Конечно, часто эти модули находятся в одном и том же файле проекта и компилируются с одними и теми же опциями, но комфорт часто приводит к забывчивости. В особенности высока цена такой забывчивости при переходе к динамически связываемым библиотекам, распределении большого проекта между несколькими группами или при замене модулей "на ходу" — в этом случае вы должны уделить максимум внимания тому, чтобы выделение и освобождение памяти выполнялось в пределах одного модуля или подсистемы.

Хорошим методом обеспечения освобождения памяти соответствующей функцией является использование shared_ptr (см. [C++TR104]). Интеллектуальный указатель shared_ptr со счетчиком ссылок может захватить свой "удалитель" в процессе конструирования. "Удалитель" — это функциональный объект (или обычный указатель на функцию), который выполняет освобождение памяти. Поскольку упомянутый функциональный объект, или указатель на функцию, является частью состояния объекта shared_ptr, модуль, выделивший память объекту, может одновременно определить функцию освобождения памяти, и эта функция будет корректно вызвана, даже если точка освобождения находится где-то в другом модуле — вероятно, относительно небольшой ценой (корректность важнее цены; см. также рекомендации 5, 6 и 8). Конечно, исходный модуль при этом должен оставаться загруженным.

Ссылки

[С++TR104]

<p>61. Не определяйте в заголовочном файле объекты со связыванием</p>Резюме

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

Обсуждение

Когда мы начинаем использовать С++, то все достаточно быстро уясняем, что заголовочный файл наподобие

// Избегайте определения объектов с внешним

// связыванием в заголовочном файле

int fudgeFactor;

string hello("hello, world!");

void foo() { /* ... */ }

будучи включен больше чем в один исходный файл, ведет при компиляции к ошибкам дублирования символов во время компоновки. Причина проста: каждый исходный файл в действительности определяет и выделяет пространство для fudgeFactor, hello и тела foo, и когда приходит время сборки (компоновки, или связывания), компоновщик сталкивается с наличием нескольких объектов, которые носят одно и то же имя и борются между собой за видимость. Решение проблемы простое — в заголовочный файл надо поместить только объявления:

extern int fudgeFactor;

extern string hello;

void foo(); // В случае объявления функции "extern"

            // является необязательным

Реальные же объявления располагаются в одном файле реализации:

int fudgeFactor;

string hello("hello, world!");

void foo() { /* ... */ }

He определяйте в заголовочном файле и статические объекты уровня пространства имен, например:

// избегайте определения объектов со статическим

// связыванием в заголовочном файле

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

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

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

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

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

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

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

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

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

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

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

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

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

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