强弱符号与强弱引
概念
就C/C++而言:
- 强符号(Strong Symbol):已初始化的全局变量。
- 弱符号(Weak symbol): 未初始化的全局变量。
- 强引用(Strong Reference): 如果未找某个符号定义,链接器会报符号未定义错误,这种引用称为强引用。
- 弱引用(Weak Reference):相对于强引用而言,如果弱引用在链接时可以找到定义,则链接器会将该引用决议(即符号对应到相应的虚地址上);未找到某个符号的定义,链接器也不会报错。
如何定义
在GCC中:
-
强符号:定义全局变量并将其初始化。如:
int strongSymbol = 1; int main() { return 0; }
-
弱符号:有两种方式:
int weakSymbol; //方式一: 定义未初始化全局变量 __attribute__(weak) weakSymbol2 = 2; //利用GCC扩展属性weak。 int main() { return 0; }
-
强引用: 我普通情况下对符号的引用都是强引用。如:
void foo(); //在别的模块定义 int main() { foo(); //强引用,在链接阶段,链接器必须看到它的定义,否则会报错。 return 0; }
-
弱引用:弱引用通过扩展关键字
__attribute__((weakref))
,如:__attribute__ ((weakref)) void foo(); //在别的模块定义 int main() { /* 弱引用,在链接阶段,链接器即使找不到它的定义,也会不会报错。 * 会延迟到程序运行时再决议,如果运行时还是找不到定义,因foo的地址为0,就会发生错误, * 可以通过条件判断 if(foo)foo; 防止运行时错误的发生。*/ foo(); return 0; }
规则
- 强符号不可定义多次。否则链接器会抱怨重复定义。但是可以只定义一个强符号,同时存在多个弱符号,链接时链接器会自动选择强符号。
- 如果没有定义强符号,但是定义了多个弱符号,那么会选择占用空间最大的。
应用场景
- 强符号和强引用就是我们平常编码最常使用的方式,就不必多说了。
- 弱符号的应用场景主要在库上,如库可以定义一个备选弱符号,如果用户程序有自定义强符号,就可以覆盖库中定义弱符号,没有的话就可以使用库中弱符号。
- 弱引用也主要是应用在库中,以在某种程度上实现程序的动态伸缩。如程序将某些扩展功能定义成弱引用,当库与程序链接在一起后,如果弱符号有被定义,则就可以被程序调用;如果去掉某些包含弱引用功能的模块程序也可以正常运行。
参考
- 程序员的自我修改 --- 链接、装载与库,第三章第五节。