Какова практическая разница между статической функцией и функцией со "скрытым" атрибутом видимости?

Я знаю, что использование ключевого слова static в C для функции ограничивает функцию единиц компиляции, в которой она определена. Теперь я просматриваю видимость символов, и я немного запутался в различии между функциями static и функцией, помеченной __attribute__((visibility("hidden"))), или с помощью параметра командной строки -fvisibility=hidden.

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

Ответ 1

Функция с __attribute__((visibility("hidden"))) не видна вне общей библиотеки, содержащей ее, но если эта библиотека была создана путем связывания foo.pic.o и bar.pic.o, то такая функция fhid может быть определена в foo.c и вызвана из bar.c. Конечно, внешний код (например, из основной программы или какой-либо другой разделяемой библиотеки) не может назвать это fhid

Таким образом, скрытая видимость применяется ко всей общей библиотеке, а не к отдельным составляющим ее компиляционным единицам.

Напротив, было бы возможно, чтобы foo.c определял функцию static void fsta(void), а для bar.c определял другую функцию static void fsta(void) (даже если это плохой вкус и ее следует избегать по соображениям удобочитаемости).

Кроме того, в принципе, функция static может быть более легко встроена или компилятор может (иногда) использовать для нее различные соглашения о вызовах.

Ответ 2

Если у вас есть функция global в общей библиотеке, которую вы хотите использовать только в контексте общей библиотеки, но не за пределами общей библиотеки, тогда вам нужно __attribute__((visiblity("hidden")))

Например:

Если у вас есть функция void foo(), определенная в Foo.c, и вы хотите, чтобы она ссылалась на Bar.c и Baz.c, которые являются единицами компиляции для создания FooBarBaz.dll (или FooBarBaz.so), тогда вы можете сделать функцию как

__attribute__((visibility("hidden"))) void foo() {}

Помните, что foo() не будет виден исполняемому файлу, который загружает dll (или файл .so) Прочтите эту статью .

Ответ 3

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

http://ohse.de/uwe/articles/gcc-attributes.html

Я могу добавить: вы можете использовать __attribute__((visibility("hidden"))) в С++ с семантикой, близкой к версии C static.