在编译链接的时候链接器需要将符号解析为相应的对象。
首先有这样几个原则:在同一个命名空间内的符号,是相互可见的。
这里的命名空间是一个很抽象的概念,例如一个function本身可以看作一个命名空间,它所有的局部变量,只在内部可见;函数执行完毕后由于栈平衡的作用使得这些局部变量全部销毁。显然可以推测,对于局部符号以及被static修饰的符号,不会存在什么符号可见性的问题。
但是对于全局符号就完全不一样了。一个全局符号(例如全局变量)可能会在多处定义或者引用,编译器为了正确的处理这些关系,便定义了强弱符号和强弱引用的概念。
强符号:一个定义并且初始化过的全局符号。例如下面:
int strong = 0;
void iamstrong() {}
弱符号:一个定义但是未初始化过的全局符号。例如:
int week;
强引用:对某个符号的显式引用。链接期间若该引用的定义不存在则会出错。
弱引用:基本上同强引用,但是链接期间若找不到该引用定义也不会报错。
下面这个程序:
void bar();
int main(void) {
bar();
return 0;
}
一般来说,如果直接编译链接,则会报bar符号找不到的链接错误。显然,这里的bar就是一个强引用。
利用GCC内置一个声明,将bar声明为弱引用,则编译链接会成功。如下所示:
__attribute__ ((weekref)) void bar();
但是这个程序运行的时候会报错,因为bar此时实际上是NULL(0)。
转载于:https://blog.51cto.com/spinlock/1128833