attribute ((visibility(“”)))
是 gcc 的编译器指令,用于设置在 shared object 中所修饰的符号对外的可见性。该修饰对 .a 文件不生效,只对 .so 库生效。
attribute ((visibility(“default”)))
该修饰用于修饰符号的可见性为默认对外可见。意思是通过该符号修饰的函数可以在 so 文件外访问到。
func.cpp:
1 | __attribute__ ((visibility("default"))) void func1(int a) { |
main.cpp:
1 |
|
1 | @└────> g++ func.cpp --shared -fPIC -o libfunc.so |
之后发现是可以编译成功的。因为该符号是可见的。
1 | @└────> nm libfunc.so | grep func |
大写的 T 表示定义在 text 段,并且可被外部引用。如果你是通过编译 .o 文件再链接为 .so 文件的,还可以使用 readelf -s 查看 .o 文件的可见性.
attribute ((visibility(“hidden”)))
该修饰用于修饰符号的可见性为默认对外不可见。意思是通过该符号修饰的函数不可以在 so 文件外访问到,只能在 so 文件内部访问到。
func.cpp:
1 | __attribute__ ((visibility("hidden"))) void func2(int a) { |
main.cpp:
1 |
|
1 | @└────> g++ func.cpp --shared -fPIC -o libfunc.so |
之后发现是可以编译失败,因为符号不可见.
1 | @└────> nm libfunc.so | grep func |
其他
1 | __attribute__ ((visibility("internal"))) |
上述两种一样是用于修饰符号, internal 对外不可见,而 protected 对外可见。
此外,在编译 so 文件时可以通过指定 -fvisibility=xxx
来指定默认的没有给出修饰的符号属性。
如:
1 | @└────> gcc -fPIC -shared -o libtest.so -fvisibility=hidden test.c |
这样在 test.c 中没用经过修饰的符号对外都不可见,而修饰为 default 的依旧对外可见。