转自:https://blog.csdn.net/starstarstone/article/details/7493144?utm_source=tuicool&utm_medium=referral

visibility用于设置动态链接库中函数的可见性,将变量或函数设置为hidden,则该符号仅在本so中可见,在其他库中则不可见。

g++在编译时,可用参数-fvisibility指定所有符号的可见性(不加此参数时默认外部可见,参考man g++中-fvisibility部分);若需要对特定函数的可见性进行设置,需在代码中使用__attribute__设置visibility属性。

编写大型程序时,可用-fvisibility=hidden设置符号默认隐藏,针对特定变量和函数,在代码中使用__attribute__ ((visibility("default")))另该符号外部可见,这种方法可用有效避免so之间的符号冲突。

下面是visibility的实例,这里extern “C”可以省略(另外两篇文章gcc __attribute__关键字举例之aliasC++覆盖系统函数的方法中extern "C"不可用省略)。

值得注意的是,visibility2.cc中可以调用fun1,原因是visibility1.o和visibility2.o同属于一个so文件。

visibility1.cc:

  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:

  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:

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

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

参考:

Function Attributes

Visibility Pragmas

GCC扩展 __attribute__ ((visibility("hidden")))

gcc __attribute__关键字举例之visibility【转】的更多相关文章

  1. attribute__关键字举例之visibility

    /** @file visibilityT.c * @note * @brief * @author * @date 2019-6-20 * @note v1.0.0 Created * @histo ...

  2. gcc __attribute__

    GNU C 的一大特色就是__attribute__ 机制.__attribute__ 可以设置函数属性(Function Attribute ).变量属性(Variable Attribute )和 ...

  3. linux内核宏container_of前期准备之gcc扩展关键字typeof

    typeof基本介绍 typeof(x) 这是它的使用方法,x可以是数据类型或者表达式.它的作用时期和sizeof类似,就是它是在编译器从高级语言(如C语言)翻译成汇编语言时起作用,这个很重要,稍后会 ...

  4. 链接加载文件gcc __attribute__ section

    在阅读源代码的过程中,发现一个头文件有引用: /** The address of the first device table entry. */ extern device_t devices[] ...

  5. gcc __thread关键字

    https://blog.csdn.net/xj178926426/article/details/54345449 EventLoop.cpp __thread EventLoop* t_loopI ...

  6. <2013 08 09> __attribute__是GCC编译器特有语法

    1. __attribute__ ((packed)) 的作用就是告诉编译器取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐,是GCC特有的语法.这个功能是跟操作系统没关系,跟编译器有关,g ...

  7. GCC的编译和安装 很好的资料

    http://blog.csdn.net/yrj/article/details/492404 1.GCC的编译和安装2.预处理    #define 可以支持不定数量的参数.    例子如下:    ...

  8. __attribute__中constructor和destructor

    1.前言 最近看到一份代码,看到一个函数前面用__attribute__((destructor))修饰,当时感觉有点怪怪的,搜了整个程序,也没发现哪个地方调用这个函数.于是从字面意思猜想,该函数会在 ...

  9. 编译器--__attribute__ ((packed))

    1. __attribute__ ((packed)) 的作用就是告诉编译器取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐,是GCC特有的语法.这个功能是跟操作系统没关系,跟编译器有关,g ...

随机推荐

  1. Beta冲刺预备

    作业链接 Beta冲刺随笔集 github地址 讨论组长是否重选的议题和结论 在Alpha阶段我们由于没有项目经验,很多技术都仅限于书本上的知识,没有真正实践过,所以出现各种各样的问题,在组长的带领下 ...

  2. GIT情况展示说明

    旧仓库:https://git.coding.net/shenbaishan/GIFT.git 公开的 新仓库:https://git.coding.net/shenbaishan/gift-sele ...

  3. PAT 甲级 1078 Hashing

    https://pintia.cn/problem-sets/994805342720868352/problems/994805389634158592 The task of this probl ...

  4. MySQL的order by时区分大小写

    Mysql 查询区分大小写 mysql查询默认是不区分大小写的 如: select * from some_table where str=‘abc'; select * from some_tabl ...

  5. A · F · O —— JLOI2018翻车记(附Day1简要题解)

    JLOI2018翻车记 并不知道该怎么写... 算了还是按照标准剧情来吧 这应该是一篇写得非常差的流水账... 2018.04.04 Day -1 省选前在机房的最后一天. 压力并不是很大,毕竟联赛 ...

  6. BZOJ4628 BJOI2016IP地址(trie)

    离线,每次修改相当于对该规则的所有匹配点的值+1,考虑在trie上打加法标记和匹配标记,匹配标记不下传,加法标记下传遇到匹配标记时清空.注意是用b时刻前缀-a时刻前缀,而不是(a-1)时刻前缀,具体我 ...

  7. #LOJ2564 SDOI2018 原题识别 主席树

    转载请注明原文地址:http://www.cnblogs.com/LadyLex/p/9057297.html 原题链接: 今天考试考了前天的SDOI考题 天啊我菜爆,只有T2拿了30分 然后考试后半 ...

  8. 【转】vi 写完文件保存时才发现是 readonly

    在MAC上编辑apache配置文件,老是忘记sudo…… readonly的文件保存时提示 add ! to override, 但这仅是对root来说的啊! 百毒了一下竟然还有解决方案!! :w ! ...

  9. 走楼梯(walk) 解题报告

    走楼梯(walk) 题意 给一个长为\(n(1\le n\le 10^5)\)序列\(\{a\}\),每次从中间挖掉\([l,r]\),然后询问最长上升子序列,强制在线. 有一档分是30000和离线, ...

  10. JavaScript -- 标签 , Break 和 Continue 语句

    break 语句用于跳出循环. continue 用于跳过循环中的一个迭代. 标签引用,break 语句可用于跳出任何 JavaScript 代码块. demo: <!DOCTYPE html& ...