强符号、弱符号、强引用、弱引用

强符号与弱符号

当多个目标文件中含有相同名字全局符号的定义,那么这些目标文件链接的时候会出现符号重复定义的错误。对于C/C++语言来说,编译器默认函数和初始化了的全局变量为强符号,未初始化的全局变量为弱符号。我们也可以通过GCC的"__attribute__((weak))"来定义任何一个强符号为弱符号。需要注意的是强符号和弱符号都是针对定义来说的,而不是引用。如下面的这段程序:

extern int ext;//是引用,非强符号也非弱符号

int weak;//弱符号
int strong = 1;//强符号
__attribute__((weak)) weak2 = 2;//弱符号

int main()
{
    return 0;
}

在上面程序中"ext"是外部变量的引用,所以非强符号也非弱符号。weak和weak2是弱符号,strong和main是强符号。对于强弱符号,编译器会按 如下的规则处理:

  • 不允许强符号被多次定义(即不同的目标文件中不能有同名的强符号);如果有多个强符号,链接器报符号重复定义错误
  • 如果一个符号在某个目标文件中是强符号,在其他文件中都是弱符号,那么选择强符号。
  • 如果一个符号在所有目标文件中都是弱符号,那么选择其中占用空间最大的一个。比如目标文件A定义全局变量a为Int型,占四个字节;目标文件B定义全局变量a为double,占八个字节,那么目标文件A和B链接后,符号a占八个字节。

 

强引用和弱引用

在外部符号引用在目标文件被最终链接成可执行文件时,如果没有找到该符号的定义,链接器就会报符号未定义错误,这种被称为强引用对于弱引用,如果该符号有定义,则链接器将该符号的引用决议,如果未定义,则链接器也不会报错,编译器不认为它是一个错误。一般对于未定义的弱引用,链接器会默认为0,或者是一个特殊值,以便程序代码被识别。弱引用和弱符号主要用于库的链接。

在GCC中我们可以通过使用"__attribute__((weakref))"这个关键字声明对一个外部函数的引用为弱应用,比如:

__attribute__((weakref)) void foo();

int main()
{
    foo();
}

上面的程序可以编译成一个可执行文件,不会报链接错误,但是在运行时,因为main函数试图调用foo函数时,foo函数的地址为0,于是发生了非法地址访问的错误。改进后的: 

__attribute__((weakref)) void foo();

int main()
{
    if(foo)
    foo();
}

 

应用

这种弱符号和弱引用对于库来说十分有用,比如在库中定义的弱符号可以被用户定义的强符号覆盖,从而使得程序可以使用自定义版本的库函数;或者程序可以对某些扩展功能模块的引用定义为弱引用,当我们将扩展模块与程序链接在一起时,可以使得程序正常链接,只是越少了相应的功能,这使得程序的功能更加容易裁剪和组合。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值