如何使静态库中的gcc链接强符号覆盖弱符号?

如何使静态库中的gcc链接强符号覆盖弱符号?,c,gcc,ld,weak-linking,C,Gcc,Ld,Weak Linking,我的问题可以总结如下: 条形图c: #include <stdio.h> void bar() { printf("bar\n"); } #include <stdio.h> void __attribute__((weak)) bar() { printf("foo\n"); } int main() { bar(); return 0; } all: gcc -c bar.c ar -rc libbar.a b

我的问题可以总结如下:

条形图c

#include <stdio.h>

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

void __attribute__((weak)) bar() {
    printf("foo\n");
}

int main() {
    bar();
    return 0;
}
all:
    gcc -c bar.c
    ar -rc libbar.a bar.o
    gcc main.c -L. -lbar
$ ./a.out
foo
输出

#include <stdio.h>

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

void __attribute__((weak)) bar() {
    printf("foo\n");
}

int main() {
    bar();
    return 0;
}
all:
    gcc -c bar.c
    ar -rc libbar.a bar.o
    gcc main.c -L. -lbar
$ ./a.out
foo
因此,由于bar.c链接到静态库libbar.a中的main.c,因此main.c中的弱符号栏不会被bar.c中的强符号覆盖


我如何告诉gcc在libbar.a中创建强符号以覆盖main.c中的弱符号?

一般来说:如果您没有在
main
中放入弱实现,链接器最终会在运行时解决它。但是,如果在
main.c
中实现它,则在链接此静态文件时,只能使用强绑定(
bar.c
)覆盖它

请阅读-它包含了很多关于这个主题的有趣的东西

我自己做了一个测试:

酒吧c


看看main1和main2。。。如果您不将任何弱实现放入
main.c
中,而是将弱实现放在库中,将强实现放在另一个库中,那么如果强库定义了
bar()

的强实现,您将能够覆盖弱实现。max.haredoom给出的答案让我感到困惑(并且它被接受)。答案涉及共享库和动态链接,而问题显然是关于使用静态库进行静态链接的行为。我认为这是误导

链接静态库时,
ld
默认情况下不关心弱/强符号:它只是将未定义的符号解析为第一个遇到的符号(因此命令行中静态库的顺序很重要)

但是,可以使用
--whole archive
选项更改此默认行为。如果将Makefile中的最后一步重写如下:

gcc main.c -L. -Wl,--whole-archive -lbar -Wl,--no-whole-archive
然后你会看到:

$ ./a.out
bar
简而言之,
--whole archive
强制链接器扫描其所有符号(包括已解析的符号)。如果有一个强符号已经被一个弱符号解析(如我们的例子),强符号将推翻弱符号


另外,还可以看到一篇关于静态库及其链接过程的文章。

谢谢。将所有弱实现分离到另一个库中是一个解决方案。Internet上对这个重要的_属性_((弱))问题的唯一参考。Thx!你看,这是一次反复试验。但是这个问题真的很有趣。谢谢+1请澄清静态链接。请不要问我为什么忽略了静态链接…这对我来说很有效,但是,我已经查看了,我认为应该注意的是,
--whole archive
选项还添加了给定库中的所有符号,这将解决此问题,但会增加可执行文件的大小,并可能产生额外的链接错误。