GCC: Каким образом видимость внутренняя "довольно бесполезная в реальном мире"?

В настоящее время я разрабатываю библиотеку для QNX (x86) с использованием GCC, и я хочу сделать некоторые символы, которые используются исключительно в библиотеке и невидимы для других модулей, особенно для кода, который использует библиотеку.

Это уже работает, но, исследуя, как его достичь, я нашел очень тревожный проход в документации GCC (см. http://gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/Code-Gen-Options.html#Code-Gen-Options, объяснение флагов -fvisibility):

Несмотря на номенклатуру, дефолт всегда означает общественность; то есть доступной для связи с внешним объектом. защищенных и внутреннее довольно бесполезно в реальном использовании, поэтому единственное другое обычно используемый параметр скрыт. Значение по умолчанию, если -fvisibility не указанный по умолчанию, т.е. сделать каждый символ общедоступным - это вызывает такое же поведение, как и предыдущие версии GCC.

Мне очень интересно, насколько видимость "внутренняя" довольно бесполезна в реальном использовании. Из того, что я понял из другого отрывка из документации GCC (http://gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/Function-Attributes.html#Function-Attributes, объяснения атрибута видимости), видимость "внутренняя" еще сильнее (более полезно для меня), чем видимость "скрыта":

Внутренняя видимость похожа на скрытую видимость, но с дополнительными специфическая для процессора семантика. Если иное не указано psABI, GCC определяет внутреннюю видимость, чтобы означать, что функция никогда вызывается из другого модуля. Сравните это со скрытыми функциями, которые, в то время как они не могут напрямую ссылаться на другие модули, могут быть косвенно ссылаются на указатели функций. Указывая, что функция не может быть вызвана извне модуля, GCC может экземпляр опускает нагрузку регистра ПИК, поскольку известно, что вызывающая функция загрузила правильное значение.

Может кто-нибудь объяснить в глубину?

Спасибо вам заблаговременно!

Ответ 1

Если вы просто хотите скрыть свои внутренние символы, просто используйте -fvisibility=hidden. Он делает именно то, что вы хотите.

Флаг internal намного больше, чем флаг hidden. Он сообщает компилятору, что совместимость с ABI не важна, так как никто, кроме модуля, никогда не будет использовать эту функцию. Если какой-то внешний код справляется с вызовом функции, он, вероятно, сработает.

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

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

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

Ответ 2

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