写在前面
上一篇文章《ENOS上段错调试记录》中有提到弱符号weak引发的段错,这篇文章来学习一下weak的用法。说来惭愧,工作了快4年,第一次见到这个语法。
weak弱符号定义
网上找了下weak符号的定义:#pragma weak to define a weakglobal symbol. This pragma is used mainly in source files for building libraries. The linker does not produce an error if it is unable to resolve a weak symbol.
对于全局的函数和变量,能不能重命名是有一定的规矩的,强、弱符号就是针对这些全局函数和变量来说的。
| 符号类型 | 对象 |
|---|---|
| 强 | 函数名,赋初值的全局变量 |
| 弱 | 未初始化的全局变量 |
当代码中存在多个强或弱的全局变量时,规则如下:
- 强符号只能定义一次,否则编译error(未使用weak修饰的都是强符号)
- 强弱符号同时存在,以强符号为准
- 没有强符号,从多个弱符号中选一个,
-fno-common这种情况下可以打出warning
这玩意的用途有点类似于1
2
3#ifndef name
#define name
#endif
代码演示
弱符号声明
两种方式,第一种
1 | extern void weak0(); |
第二种方式
1 | void __attribute__((weak)) weak0(); |
规则演示
下面通过三段代码来演示上诉的3条规则。
main.c
main.c里面调用了2个声明为弱符号的函数,分别是weak0和weak1
1 | #include <stdio.h> |
weak.c
weak.c中定义了两个函数(weak0和weak1),并将之声明为弱符号
1 | #include <stdio.h> |
strong.c
strong.c中重复定义了这两个函数,不做声明。
1 | #include <stdio.h> |
不同编译组合及其输出情况
单独编译main.c
此处弱符号函数链接不成功,但是不会报编译错误,函数名所代表的地址为nil
如果这里依然调用它,那么便会如前面文章中提到的一样产生段错。
编译main.c+weak.c
弱符号链接成功,可以正常调用。
编译main.c+weak.c+strong.c
当出现强符号定义时,弱符号定义不起作用