如果目标文件对外部目标文件符号进行强引用,但在链接成可执行文件时不能被正确的决议(好奇怪的名称,看看p_51),链接器就会报错,这是对于强引用(Strong Reference)而言的。
与之相对应还有一种弱引用(Weak Reference),在处理弱引用时,如果该符号有定义,则链接器将对该符号的引用进行决议,如果该符号未被定义,则链接器对于该引用不报错。
链接器处理强引用和弱引用的过程几乎一样,但是对于未定义的弱引用,链接器不认为它是一个错误;一般,对于未定义的弱引用,链接器默认其值为0,或者是一个特殊值,以便于程序代码能够识别。
弱引用和弱符号主要用于库的链接过程。
在GCC中,使用__attribute__((weakref))这个扩展关键字来声明对一个外部函数的引用为弱引用,例如下面这段代码:
__attribute__((weakref)) void foo();
int main()
{
foo();
}
我们可以将它编译成一个可执行文件,GCC并不会报链接错误,但是在运行这个可执行文件时,会发生错误。因为当main函数试图调用foo函数时,
foo函数的地址为0,于是发生了非法地址访问的错误。一个改进的例子是:
__attritube__((weakref)) void foo();
int main ()
{
if(foo)
foo();
return 0;
}
弱符号可以被用户定义的强符号所覆盖,从而使得程序可以使用自定义版本的库函数;
库函数可以对某些扩展功能模块的引用声明为弱引用,当我们将扩展模块与程序链接在一起时,功能模块就可以正常使用;如果我们去掉某些功能模块,那么程序也可以正常链接,只是缺少了相应的功能,这使得程序的功能更加容易裁剪和组合。
附:
在Linux程序设计中,如果一个程序被设计成可以支持单线程或多线程的模式,就可以通过弱引用的方法来判断当前的程序是链接到了单线程的Glibc库还是
多线程的Glibc库,从而执行单线程版本的程序或多线程版本的程序。我们可以在程序中定义一个pthread_create函数的弱引用,然后程序在运行时动态
判断是否链接到pthread库从而决定执行多线程版本还是单线程版本:
1 #include
2 #include
3
4 __attribute__ ((weak)) int pthread_create(pthread_t *, const pthread_attr_t *, void *(*)(void*), void *);
5
6 int main(void)
7 {
8 if(pthread_create)
9 {
10 printf("This is multi-thread version! \n");
11 // run the multi-thread version
12 // main_multi_thread()
13 }
14 else
15 {
16 printf("This is single-thread version! \n");
17 // run the single-thread version
18 // main_single_thread()
19 }
20 return 0;
21 }
gcc pthread.c -o pt
gcc pthread.c -lpthread -o pt