gcc/g++中weak弱符号及alias别名
最近查看linux内核代码时,表现了一些编译器选项如__attribute_((weak))、__attribute__( (alias("target"))),一开始不了解,后来自己查看资料及书籍算是对gcc的这个编译属性有了一定的认识。
一、先了解weak属性。
__attribute__((weak))表示为弱符号属性,所谓的弱符号是针对于强符号来说的,我们定义的全局已初始化变量及全局函数等都是属于强符号,在链接时如果有多个强符号就会报错误;而弱符号主要指未初始化的全局变量或通过__attribute__((weak))来显式申明的变量或函数。
/* file:weak_test.c */ void weak_func_test(void) __attribute__((weak)); /* 显式申明为weak,属于弱符号(函数) */
int weak_var_test; /* 未初始化的全局变量,属于弱符号 */ #ifdef WEAK_SYM
void weak_func_test(void)
{
printf("%s:%s.c in\n", __FILE__, __func__);
}
#endif int main()
{
printf("weak_var_test:%d\n", weak_var_test);
weak_func_test();
return ;
} /* file:symbol.c */
int weak_var_test = ; /* 已初始化的全局变量,属于强符号 */
/* 全局函数属于强符号 */
void weak_func_test(void)
{
printf("%s:%s() in\n", __FILE__, __func__);
}
1、使用编译命令gcc weak_test.c symbol.c DWEAK_SYM -o weak_test,执行./weak_test,打印weak_var_test为6666,函数weak_func_test()打印symblo.c:weak_func_test() in(注意是symbol.c的函数),从执行结果看symbol.c的weak_var_test及weak_func_test覆盖了weak_test.c的符号,说明链接时强弱符号都存在时以强符号为准;
2、再使用编译命令而gcc weak_test.c -DWEAK_SYM -o weak_test,执行./weak_test,打印weak_var_test为0(未初始化的全局变量编译器默认为0),函数执行打印weak_test.c:weak_func_test() in(这时是weak_test.c的函数),说明连接时如果只有弱符号时以弱符号为准。
3、继续编译gcc weak_test.c -o
weak_test,这时可能大家会有疑问,weak_func_test函数没有实现,那么链接的时候应该会报错吧;实际上肯定是不会的,就是因为我们
将这个函数显式的申明为weak symbol,申明为weak
symbol的函数在.o目标文件里面是以WEAK及UND形式存在的,符号的地址为0,具体可以用readelf -s 命令查看。
那么这种情况下只有弱符号weak_func_test存在,最终链接时也以弱符号为准,只不过此函数的地址为0,所以这时我们去执行./weak_test的时候必然会有segement fault的错误产生,就是因为去访问了null指针。
4、弱符号还有一个规则,就是两个都是弱符号时,以内存占用大小较大的那个符号为准。比如未初始化的char var和long var同时存在时,链接器以实际sizeof(long)的大小来给var分配空间,实例就不讲述了,遇见这种情况需要额外小心。
小结:weak属性基本已讲述完成,其实弱符号在实际中也有很多应用。比如说在一个库里面实现某个函数,申明为弱符号,在某种情况下我们可以用自己的代码去覆盖库的实现从而重新去实现某个函数,达到定制化的目的。
二、接下去讲述alias属性,alias属性比较简单,从字面意思理解就是给符号设置一个别名,相当于取一个外号。使用方法如下:
void func(void);
void alias_func(void) __attribute__((alias("func"))); 需要注意c++的符号修饰机制!
这样的意思就是函数func的别名或外号是alias_func,那么就是调用alias_func()和func()的效果是一样的,有兴趣的话可以自己写代码验证。这时需要主意func函数必须是要有定义的,否则会编译报错的。
三、最后还有一个属性是weakref活weakref("target")
__attribute__((weakref))为弱引用,请注意引用与定义的区别。weakref就是申明某个引用为弱引用,弱引用时如果需引用符号不存在也不会链接出错,而是将需要引用的符号定义为WEAK属性及0地址(跟前面的WEAK属性很相似吧)。
weakref的用法有点特别,必须要配合alias使用及必须是static定义。__attribute__((weak("target")))相当于__attribute__((weakref,alias("target"))),以下看个实例:
/*
** weakref_test.c
*/ /* 申明func_alias函数func的带弱引用的别名 */
void func(void)
{
printf("func:%s in\n", __FUNC__);
} static void func_alias(void) __attribute__((weakref,alias("func"))); int main()
{
func_alias(); /* 相当于调用func */
return ;
}
注意到前面alias属性如果func不存在时申明alias会出错,通过weakref方法,可以让func未定义就可以编译通过,使用static
void alias_func(void) __attribute__((weakref,
alias("func")))时即使func未定义也能链接通过,只不过func或alias_func的地址为0,可以去掉func的实现,验证一下
即可。
上面讲述的关于weak、alias、weakref属性都是自己的一些总结,有很多不合理之处,还望大家指出,一起探讨。
gcc版本信息:gcc version 4.4.7
http://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes
gcc/g++中weak弱符号及alias别名的更多相关文章
- GCC中的弱符号与强符号
GCC中的弱符号与强符号 我们经常在编程中碰到一种情况叫符号重复定义.多个目标文件中含有相同名字全局符号的定义,那么这些目标文件链接的时候将会出现符号重复定义的错误.比如我们在目标文件A和目标文件B都 ...
- GNU C/C++ __attributes__ GCC中的弱符号与强符号
最近在看一些源代码,遇到了一些使用__attribute__修饰函数和变量的属性方面的代码,不是太了解,很是汗颜,再此做个总结: GCC使用__attribute__关键字来描述函数,变量和数据类 ...
- C语言中的弱符号(weak)用法及实例
一 符号概念: 在C语言中,有强符号和弱符号,符号简单来说就是函数.变量的名字,对于全局(非局部.非static)的函数和变量,能不能重名是有一定规矩的,强.弱符号就是针对这些全局函数和变量来说的. ...
- Linux下gcc/g++中-I(i的大写)、-L和-l
-I(i的大写)include头文件非标准库中存在的也不是在当前文件夹下的,需要将地址用-i(大写)包含例:-I /home/src/-L用到的函数或操作非标准库下的,需要将库存在的地址用-L包含,库 ...
- 在cmd中使用doskey来实现alias别名功能
作为一枚网络工程师,经常就是面对一堆黑框框,也是就是终端.不同操作系统.不同厂家的目录,功能相同但是键入的命令又大不相同,这些差异化容易让脑子混乱.比如华为.思科.H3C.锐捷的设备, ...
- C++中弱符号(弱引用)的意义及实例
今天读别人代码时看到一个“#pragma weak”,一时没明白,上网研究了一个下午终于稍微了解了一点C.C++中的“弱符号”,下面是我的理解,不正确的地方望大家指正. 本文主要从下面三个方面讲“弱符 ...
- C语言强、弱符号,强、弱引用
C语言强.弱符号,强.弱引用 符号定义 在编程中我们经常碰到符号重复定义的情况,当我们在同一个作用域内重复定义同一个变量时,有时是因为误写,有时是文件之间的冲突,编译器的处理方式就是报错: redef ...
- gcc/g++多版本切换 (ubuntu18.04)
使用Ubuntu18.04已经有一段时间了,在使用过程中经常需要处理不同软件的编译工作,但是这时候就遇到这样一个问题,那就是不同软件,甚至是同一个软件的不同版本都会使用不同版本的gcc/g++来进行编 ...
- git-bash的alias别名设置
正常需要设置别名时,直接使用 alias gs="git status" 输入上边的命令之后,就可以使用gs(命令)代替git status(命令),这是一种设置别名简化输入,提升 ...
随机推荐
- 发布 Rafy 源码到 GitHub
最近项目组开始使用 Git 来作为源码管理.我今天就顺便把 Rafy 的源码也迁移到了 github 上,方便大家使用.这是项目的地址:https://github.com/zgynhqf/raf ...
- Rafy 领域实体框架 - 树型实体功能(自关联表)
在 Rafy 领域实体框架中,对自关联的实体结构做了特殊的处理,下面对这一功能进行讲解. 场景 在开发数据库应用程序时,往往会遇到自关联表的场景.例如,分类信息.组织架构中的部门.文件夹信息等,都 ...
- sealed、new、virtual、abstract与override 趣解
1. sealed——“断子绝孙” 密封类不能被继承.密封方法可以重写基类中的方法,但其本身不能在任何派生类中进一步重写.当应用于 方法或属性时,sealed修饰符必须始终与override一起使用. ...
- C#正则表达式Regex常用匹配
使用Regex类需要引用命名空间:using System.Text.RegularExpressions; 利用Regex类实现验证 示例1:注释的代码所起的作用是相同的,不过一个是静态方法,一个是 ...
- C#学习笔记-封装
前言 说起来惭愧,学了大半年的C#,其实最开始就接触到了封装的部分,但是一直模模糊糊的弄不清楚,也觉得没什么影响就没怎么在意,现在才开始认真的看这部分内容,看懂了过后好多东西清晰了不少,才发现封装这个 ...
- luogg_java学习_08_设计模式_API
这篇博客总结了1天整,希望自己以后返回来看的时候理解更深刻,也希望可以起到帮助初学者的作用. 转载请注明 出自 : luogg的博客园 , 设计模式 在长期开发过程中,为了解决某些固定问题, 总结出的 ...
- linux 安装rz sz命令
wget http://www.ohse.de/uwe/releases/lrzsz-0.12.20.tar.gz tar zxvf lrzsz-0.12.20.tar.gz cd lrzsz-0.1 ...
- [moka同学转载]Yii2 checkBookList的使用
use yii\helpers\Html; use yii\helpers\ArrayHelper model层代码 $model = new Model()//要存储的model $aclb = A ...
- [转载] php用csv文件导出大量数据
header ( "Content-type:application/vnd.ms-excel" ); header ( "Content-Disposition:fil ...
- java泛型详解
http://www.cnblogs.com/lwbqqyumidi/p/3837629.html