强符号,弱符号

Posted petewell

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了强符号,弱符号相关的知识,希望对你有一定的参考价值。

原文引用https://www.dazhuanlan.com/2019/08/26/5d6304ae4bca7/


对于链接器来说,所有的全局符号可分为两种:强符号(Strong symbols),弱符号(Weak symbols)。gcc的attribute中有个attribute((weak)),就是用来声明这个符号是弱符号的。gcc手册中这样写道:

The weak attribute causes the declaration to be emitted as a weak symbol rather than a global. This is primarily useful in defining library functions which can be overridden in user code, though it can also be used with non-function declarations. Weak symbols are supported for ELF targets, and also for a.out targets when using the GNU assembler and linker.
对于这个gcc扩展,这里作了一个简洁的介绍。我们来看更通用的情况。;)

一般来说,函数和已初始化的变量是强符号,而未初始化的变量是弱符号。对于它们,下列三条规则适用:

1. 同名的强符号只能有一个。
2. 有一个强符号和多个同名的弱符号是可以的,但定义会选择强符号的。
3. 有多个弱符号时,链接器可以选择其中任意一个。

这三条规则看起来很好理解,其实不然,尤其是当这些弱符号类型和强符号不同时!表面上看起来正确的进程会导致严重的错误!考虑下面这个csapp中的例子:

===a.c===
int x=7;
int y=5;
p1()

===b.c===
double x;
p2()

我们把它们一起编译,并且在p2()函数中给x赋值,你会发现,y也改变了! 虽然x被看作是double,但其定义会取a.c中的int x,也就是说,在b.c中会把a.c中的int x当double来用!这当然是错误!之所以会这样,就是因为上面的规则2。避免这种错误的一个方法是,给gcc加上-fno-common选项。

关于弱符号,man手册中这样解释到:

以上是关于强符号,弱符号的主要内容,如果未能解决你的问题,请参考以下文章

浅谈C语言中的强符号弱符号强引用和弱引用

强符号,弱符号

强符号与弱符号

GCC中的弱符号与强符号

如何使静态库中的 gcc 链接强符号覆盖弱符号?

强弱符号关系