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


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

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

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

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

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

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

2 15

2 ответа:

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

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

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

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

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

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