本文僅做備用,請參見原文。
visibility用於設置動態鏈接庫中函數的可見性,將變量或函數設置為hidden,則該符號僅在本so中可見,在其他庫中則不可見。
g++在編譯時,可用參數-fvisibility指定所有符號的可見性(不加此參數時默認外部可見,參考man g++中-fvisibility部分);若需要對特定函數的可見性進行設置,需在代碼中使用__attribute__設置visibility屬性。
編寫大型程序時,可用-fvisibility=hidden設置符號默認隱藏,針對特定變量和函數,在代碼中使用__attribute__ ((visibility("default")))另該符號外部可見,這種方法可用有效避免so之間的符號沖突。
下面是visibility的實例,這里extern “C”可以省略(另外兩篇文章gcc __attribute__關鍵字舉例之alias 和C++覆蓋系統函數的方法 中extern "C"不可用省略)。
值得注意的是,visibility2.cc中可以調用fun1,原因是visibility1.o和visibility2.o同屬於一個so文件。
visibility1.cc:
#include <stdio.h>
extern "C" void fun1()
{
printf("in %s\n",__FUNCTION__);
}
__attribute__ ((visibility("hidden"))) void fun1();//若編譯此文件時使用了參數-fvisibility=hidden,則此行可以省略
visibility2.cc:
#include <stdio.h>
extern "C" void fun1();
extern "C" void fun2()
{
fun1();
printf("in %s\n",__FUNCTION__);
}
__attribute__ ((visibility("default"))) void fun2();//若編譯此文件時沒有使用參數-fvisibility或設置參數-fvisibility=default,則此行可以省略
main.cc:
extern "C" void fun1();
extern "C" void fun2();
int main()
{
fun1();
fun2();
return 0;
}
Makefile:
all:test
test:main.o libvisibility.so
g++ -o test main.o -lvisibility -L .
main.o::main.cc
g++ -c main.cc
libvisibility.so:visibility1.o visibility2.o
g++ -shared -o libvisibility.so visibility1.o visibility2.o
visibility1.o:visibility1.cc
g++ -fvisibility=hidden -fPIC -c visibility1.cc
visibility2.o:visibility2.cc
g++ -fvisibility=hidden -fPIC -c visibility2.cc
clean:
rm -f *.o *.so test
$ make g++ -c main.cc g++ -fvisibility=hidden -fPIC -c visibility1.cc g++ -fvisibility=hidden -fPIC -c visibility2.cc g++ -shared -o libvisibility.so visibility1.o visibility2.o g++ -o test main.o -lvisibility -L . main.o: In function `main': main.cc:(.text+0x5): undefined reference to `fun1' collect2: ld returned 1 exit status make: *** [test] Error 1
使用readelf對各個.o文件分析可以看到,fun1的Vis屬性為HIDDEN,fun2的Vis屬性為DEFAULT:
$ readelf -s visibility1.o|grep fun
6: 0000000000000007 5 OBJECT LOCAL DEFAULT 6 _ZZ4fun1E12__FUNCTION__
12: 0000000000000000 30 FUNC GLOBAL HIDDEN 2 fun1
$ readelf -s visibility2.o|grep fun
6: 0000000000000007 5 OBJECT LOCAL DEFAULT 6 _ZZ4fun2E12__FUNCTION__
12: 0000000000000000 35 FUNC GLOBAL DEFAULT 2 fun2
15: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND fun1
$ readelf -s libvisibility.so|grep fun
9: 00000000000006ac 35 FUNC GLOBAL DEFAULT 12 fun2
41: 000000000000071d 5 OBJECT LOCAL DEFAULT 14 _ZZ4fun1E12__FUNCTION__
43: 0000000000000729 5 OBJECT LOCAL DEFAULT 14 _ZZ4fun2E12__FUNCTION__
48: 000000000000068c 30 FUNC LOCAL HIDDEN 12 fun1
54: 00000000000006ac 35 FUNC GLOBAL DEFAULT 12 fun2
參考:
GCC擴展 __attribute__ ((visibility("hidden")))