我知道在函数上使用staticC 中的关键字会将函数限制为定义它的编译单元。我现在正在研究符号可见性,我对static函数和用 标记的函数__attribute__((visibility("hidden")))或使用-fvisibility=hidden命令行选项之间的区别有点困惑。
我有一种感觉,这些在幕后改变事物的方式根本不一样,但我不知道区别是什么,也不知道在实际代码中使用它们时意味着什么。两者之间有什么变化,您什么时候想使用其中一个?
我知道在函数上使用staticC 中的关键字会将函数限制为定义它的编译单元。我现在正在研究符号可见性,我对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.