Spec-Zone.ru › GCC 15

8.3 Неопределённое связывание

В C++ есть несколько конструкций, которым требуется место в объектном файле, но которые не связаны явно с одной единицей трансляции. Говорят, что такие конструкции имеют «неопределённое связывание». Как правило, такие конструкции генерируются везде, где они нужны, хотя иногда можно поступить более рационально.

Встраиваемые функции

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

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

Виртуальные таблицы

В большинстве компиляторов виртуальные функции C++ реализуются с помощью таблицы поиска, называемой виртуальной таблицей. Виртуальная таблица содержит указатели на виртуальные функции, предоставляемые классом, а каждый объект класса содержит указатель на свою виртуальную таблицу (или таблицы — в некоторых случаях множественного наследования). Если класс объявляет какие-либо невстраиваемые непустые виртуальные функции, первая из них выбирается в качестве «ключевого метода» класса, и виртуальная таблица генерируется только в той единице трансляции, где определён ключевой метод.

Примечание: Если выбранный ключевой метод впоследствии определяется как встраиваемый, виртуальная таблица всё равно генерируется в каждой единице трансляции, где он определён. Убедитесь, что все встраиваемые виртуальные функции объявлены встраиваемыми в теле класса, даже если они там не определены.

Объекты type_info

Для реализации ‘dynamic_cast’, ‘typeid’ и обработки исключений в C++ необходимо записывать сведения о типах. Для полиморфных классов (классов с виртуальными функциями) объект ‘type_info’ записывается вместе с виртуальной таблицей, чтобы ‘dynamic_cast’ мог определить динамический тип объекта класса во время выполнения. Для всех остальных типов объект ‘type_info’ записывается при его использовании: при применении ‘typeid’ к выражению, выбрасывании объекта или ссылке на тип в предложении catch либо в спецификации исключений.

Инстанцирования шаблонов

Большинство сведений в этом разделе также относится к инстанцированиям шаблонов, но есть и другие варианты. См. Где же шаблон?.

При использовании GNU ld версии 2.8 или новее в системе ELF, например GNU/Linux или Solaris 2, либо в Microsoft Windows, дублирующиеся копии этих конструкций удаляются на этапе компоновки. Это называется поддержкой COMDAT.

Для целевых платформ, не поддерживающих COMDAT, но поддерживающих слабые символы, GCC использует их. Благодаря этому одна копия заменяет все остальные, однако неиспользуемые копии по-прежнему занимают место в исполняемом файле.

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

Другой способ управления размещением этих конструкций описан в разделе Объявления и определения в одном заголовочном файле.

© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-15.3.0/gcc/Vague-Linkage.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API