gcc __attribute__ 关键字举例之 visibility

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  

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

使用 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_starstarstone的博客-CSDN博客

(SAW:Game Over!) 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值