我知道在函数上使用static
C 中的关键字会将函数限制为定义它的编译单元。我现在正在研究符号可见性,我对static
函数和用 标记的函数__attribute__((visibility("hidden")))
或使用-fvisibility=hidden
命令行选项之间的区别有点困惑。
我有一种感觉,这些在幕后改变事物的方式根本不一样,但我不知道区别是什么,也不知道在实际代码中使用它们时意味着什么。两者之间有什么变化,您什么时候想使用其中一个?
我知道在函数上使用static
C 中的关键字会将函数限制为定义它的编译单元。我现在正在研究符号可见性,我对static
函数和用 标记的函数__attribute__((visibility("hidden")))
或使用-fvisibility=hidden
命令行选项之间的区别有点困惑。
我有一种感觉,这些在幕后改变事物的方式根本不一样,但我不知道区别是什么,也不知道在实际代码中使用它们时意味着什么。两者之间有什么变化,您什么时候想使用其中一个?
一个函数__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
函数可以更容易地内联,或者编译器可以(有时)为它使用不同的调用约定。
如果您在共享库中有一个global
函数,您只想在共享库的上下文中使用,而不是在共享库之外使用 - 那么您需要__attribute__((visiblity("hidden")))
例如:
如果您在其中void foo()
定义了一个函数Foo.c
并且您希望它引用它Bar.c
以及Baz.c
要生成哪些编译单元FooBarBaz.dll
(或 FooBarBaz.so),那么您可以将该函数设为
__attribute__((visibility("hidden"))) void foo() {}
请记住,加载(或 .so 文件)foo()
的可执行文件将不可见阅读本文dll
隐藏可见性表示该符号不会被放入动态符号表中,因此没有其他“模块”(可执行文件或共享库)可以直接引用它。
http://ohse.de/uwe/articles/gcc-attributes.html
我可以补充:您可以__attribute__((visibility("hidden")))
在 C++ 中使用语义接近 C 版本的static
.