强弱符号的问题

2021-03-05  本文已影响0人  wayyyy

// fun.c

#include <stdio.h>
void func()  
{
    printf("func\n");
}

// mian.c

#include <stdio.h>
void func()
{
    printf("func\n");
}
int main(void)
{
    func();
    return 0;
}

gcc main.c fun.c

/tmp/ccxn0naT.o: In function `func':
main.c:(.text+0x0): multiple definition of `func'
/tmp/ccgZJUf1.o:fun.c:(.text+0x0): first defined here
collect2: error: ld returned 1 exit status

平常会遇到一种错误就是重定义的问题,这个问题本质上是强弱符号的问题。

强符号和弱符号

编译器默认函数和初始化了的全局变量为强符号,未初始化的全局变量为弱符号。

int num1;        // 未初始化全局变量,弱符号
int num2 = 10;   // 已初始化全局变量,强符号
void func()      // 函数强符号
{
    printf("func\n");
}

但是我们也可以用__attribute__((weak))来修饰,将一个强符号转换为弱符号。

__attribute__((weak)) int num2 = 2222;  // 使用标识修饰的弱符号
利用强弱符号规则制作插件

实现一个类似插件的功能:

// main.c

#include <stdio.h>
__attribute__((weak)) void foo();

void test()
{
    // 如果是强符号,说明链接了外部插件,使用外部定义
    if (foo)
    {
        foo();
    }
    else
     // 弱符号,走默认逻辑
    {
        printf("foo\n");
    }
}

int main()
{
    test();
}

制作插件库:

// plugin.c

#include<stdio.h>

void foo()
{
    printf("plugin foo\n");
}
$ gcc -c plugin.c -o plugin.o
$ ar -rcs libplugin.a plugin.o

链接插件库:

# gcc -o main main.c -L. -Wl,--whole-archive -lplugin -Wl,--no-whole-archive
# ./main
  plugin foo 

这里需要加上-Wl,--whole-archive,该选项会将插件库中所有符号都链接进来,若非如此,在main.o中已经有了foo符号,将不会链接进来,而在此之后,又要将该选项恢复。最终我们可以通过nm命令看到foo符号已经不再是W了。

上一篇 下一篇

猜你喜欢

热点阅读