Какова практическая разница между статической функцией и функцией со "скрытым" атрибутом видимости?
Я знаю, что использование ключевого слова 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
.