gcc __attribute__关键字举例之visibility

来源:互联网 发布:小米电视怎么设置网络 编辑:程序博客网 时间:2024/05/16 00:47

http://blog.csdn.net/starstarstone/article/details/7493144?utm_source=tuicool



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:

[cpp] view plaincopy
  1. #include <stdio.h>  
  2. extern "C" void fun1()  
  3. {  
  4.   printf("in %s\n",__FUNCTION__);  
  5. }  
  6. __attribute__ ((visibility("hidden"))) void fun1();//若编译此文件时使用了参数-fvisibility=hidden,则此行可以省略  

    visibility2.cc:

[cpp] view plaincopy
  1. #include <stdio.h>  
  2. extern "C" void fun1();  
  3. extern "C" void fun2()  
  4. {  
  5.   fun1();  
  6.   printf("in %s\n",__FUNCTION__);  
  7. }  
  8. __attribute__ ((visibility("default"))) void fun2();//若编译此文件时没有使用参数-fvisibility或设置参数-fvisibility=default,则此行可以省略  

    main.cc:

[cpp] view plaincopy
  1. extern "C" void fun1();  
  2. extern "C" void fun2();  
  3. int main()  
  4. {  
  5.   fun1();  
  6.   fun2();  
  7.   return 0;  
  8. }  

    Makefile:

[plain] view plaincopy
  1. all:test  
  2. test:main.o libvisibility.so  
  3.         g++ -o test main.o -lvisibility -L .  
  4. main.o::main.cc  
  5.         g++ -c main.cc  
  6. libvisibility.so:visibility1.o visibility2.o  
  7.         g++ -shared -o libvisibility.so visibility1.o visibility2.o  
  8. visibility1.o:visibility1.cc  
  9.         g++ -fvisibility=hidden -fPIC -c visibility1.cc  
  10. visibility2.o:visibility2.cc  
  11.         g++ -fvisibility=hidden -fPIC -c visibility2.cc  
  12. clean:  
  13.         rm -f *.o *.so test  

编译和输出:

[plain] view plaincopy
  1. $ make  
  2. g++ -c main.cc  
  3. g++ -fvisibility=hidden -fPIC -c visibility1.cc  
  4. g++ -fvisibility=hidden -fPIC -c visibility2.cc  
  5. g++ -shared -o libvisibility.so visibility1.o visibility2.o  
  6. g++ -o test main.o -lvisibility -L .  
  7. main.o: In function `main':  
  8. main.cc:(.text+0x5): undefined reference to `fun1'  
  9. collect2: ld returned 1 exit status  
  10. make: *** [test] Error 1   

可以看到,main()中可以不可用调用fun1,可以调用fun2,因为fun1已经设置为外部不可见,fun2设置为外部可见。

使用readelf对各个.o文件分析可以看到,fun1的Vis属性为HIDDEN,fun2的Vis属性为DEFAULT:

[plain] view plaincopy
  1. $ readelf -s visibility1.o|grep fun  
  2.      6: 0000000000000007     5 OBJECT  LOCAL  DEFAULT    6 _ZZ4fun1E12__FUNCTION__  
  3.     12: 0000000000000000    30 FUNC    GLOBAL HIDDEN    2 fun1  
  4.   
  5. $ readelf -s visibility2.o|grep fun  
  6.      6: 0000000000000007     5 OBJECT  LOCAL  DEFAULT    6 _ZZ4fun2E12__FUNCTION__  
  7.     12: 0000000000000000    35 FUNC    GLOBAL DEFAULT    2 fun2  
  8.     15: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND fun1  
  9.   
  10. $ readelf -s libvisibility.so|grep fun  
  11.      9: 00000000000006ac    35 FUNC    GLOBAL DEFAULT   12 fun2  
  12.     41: 000000000000071d     5 OBJECT  LOCAL  DEFAULT   14 _ZZ4fun1E12__FUNCTION__  
  13.     43: 0000000000000729     5 OBJECT  LOCAL  DEFAULT   14 _ZZ4fun2E12__FUNCTION__  
  14.     48: 000000000000068c    30 FUNC    LOCAL  HIDDEN   12 fun1  
  15.     54: 00000000000006ac    35 FUNC    GLOBAL DEFAULT   12 fun2  

参考:

Function Attributes

Visibility Pragmas

GCC扩展 __attribute__ ((visibility("hidden")))
0 0
原创粉丝点击