gcc __attribute__关键字举例之visibility【转】
转自: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__关键字举例之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("hidden")))
gcc __attribute__关键字举例之visibility【转】的更多相关文章
- attribute__关键字举例之visibility
/** @file visibilityT.c * @note * @brief * @author * @date 2019-6-20 * @note v1.0.0 Created * @histo ...
- gcc __attribute__
GNU C 的一大特色就是__attribute__ 机制.__attribute__ 可以设置函数属性(Function Attribute ).变量属性(Variable Attribute )和 ...
- linux内核宏container_of前期准备之gcc扩展关键字typeof
typeof基本介绍 typeof(x) 这是它的使用方法,x可以是数据类型或者表达式.它的作用时期和sizeof类似,就是它是在编译器从高级语言(如C语言)翻译成汇编语言时起作用,这个很重要,稍后会 ...
- 链接加载文件gcc __attribute__ section
在阅读源代码的过程中,发现一个头文件有引用: /** The address of the first device table entry. */ extern device_t devices[] ...
- gcc __thread关键字
https://blog.csdn.net/xj178926426/article/details/54345449 EventLoop.cpp __thread EventLoop* t_loopI ...
- <2013 08 09> __attribute__是GCC编译器特有语法
1. __attribute__ ((packed)) 的作用就是告诉编译器取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐,是GCC特有的语法.这个功能是跟操作系统没关系,跟编译器有关,g ...
- GCC的编译和安装 很好的资料
http://blog.csdn.net/yrj/article/details/492404 1.GCC的编译和安装2.预处理 #define 可以支持不定数量的参数. 例子如下: ...
- __attribute__中constructor和destructor
1.前言 最近看到一份代码,看到一个函数前面用__attribute__((destructor))修饰,当时感觉有点怪怪的,搜了整个程序,也没发现哪个地方调用这个函数.于是从字面意思猜想,该函数会在 ...
- 编译器--__attribute__ ((packed))
1. __attribute__ ((packed)) 的作用就是告诉编译器取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐,是GCC特有的语法.这个功能是跟操作系统没关系,跟编译器有关,g ...
随机推荐
- opencv2 用imwrite 抽取并保存视频图像帧
最近在写一个车辆检测程序,程序中需要获取图像帧,并保存为图片,且放到指定目录中去,我在网上查了很多发现都是opencv1的有关操作,没有opencv2的操作,我参考网上的例子,结合着用opencv2新 ...
- 冲刺Two之站立会议2
今天我们进行了主界面部分的设置,因为它包含的部分有很多,所以就只能它拆分进行一一突破.今天主要完成了主界面的框架搭建,以及添加了需要的按钮,包括好友管理,退出登录,开启聊天通信界面的内容等.
- hybrid项目h5页路由回退问题解决
问题描述: 在hybrid项目里现有h5页A.B.C三个页面,均采用vue开发.其中A.B页采用原生头部,C页采用h5头部.A页通过点击a链接进入B页,B页以同样的方式进入C页,再依次点击各业返回按钮 ...
- 关于给C盘扩容以及动态磁盘
2019.4.5 周五 磁盘分为基本磁盘和动态磁盘 基本磁盘转动态磁盘是很容易的 https://jingyan.baidu.com/article/59a015e3a3d504f7948865b1. ...
- JwtUtils 工具类
/** * jwt工具类 */ public class JwtUtils { public static final String SUBJECT = "onehee"; *** ...
- js写2048游戏代码
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...
- LOG4J 的配置
公司启动全国支票影像系统,有这样一个功能是和消息中间件打交道,需要记录每一个报文出错情况,因为方便后期开发人员的调试,我选用了log4j作为日志记录,好了废话不多说了! 第一步:首先建立一个WEB工程 ...
- pgm4
这部分 cover 两个比较特殊的情形,一个是 Gaussian networks,一个是 exponential family. 正态分布常见的参数化策略是均值 和协方差矩阵 ,另一种是使用 inf ...
- 【Revit API】改变填充区域的填充样式
话不多说,直接上代码 var target = pattern.Target; var name = pattern.Name; var fpElem = FillPatternElement.Get ...
- 20个令人惊叹的深度学习应用(Demo+Paper+Code)
20个令人惊叹的深度学习应用(Demo+Paper+Code) 从计算机视觉到自然语言处理,在过去的几年里,深度学习技术被应用到了数以百计的实际问题中.诸多案例也已经证明,深度学习能让工作比之前做得更 ...