弱引用和强引用

如果目标文件对外部目标文件符号进行强引用,但在链接成可执行文件时不能被正确的决议(好奇怪的名称,看看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 <stdio.h>                                                                                         
      2 #include <pthread.h>
      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

原文地址:https://www.cnblogs.com/openix/p/2834872.html