【问题标题】:Why doesn't __attribute__((constructor)) work in a static library?为什么 __attribute__((constructor)) 不能在静态库中工作?
【发布时间】:2019-06-25 21:52:21
【问题描述】:

在下面的例子中,程序应该打印"foo called\n"

// foo.c
#include <stdio.h>

__attribute__((constructor)) void foo()
{
    printf("foo called\n");
}

// main.c
int main()
{
    return 0;
}

如果程序是这样编译的,它可以工作:

gcc -o test main.c foo.c

但是,如果 foo.c 被编译成静态库,则程序不会打印任何内容。

gcc -c main.c
gcc -c foo.c
as rcs foo.a foo.o
gcc -o test foo.a main.o

为什么会这样?

【问题讨论】:

  • 为什么投反对票?有什么不对吗?
  • 不确定(不是我!)但也许有人不同意你这么快回答你自己的问题?
  • 嗯,我只是想为该网站添加一个有用的参考,以解决一个不明显的问题。常见问题解答表明回答自己的问题是一件好事(实际上在第一部分)。

标签: c constructor attributes static-libraries


【解决方案1】:

链接器不会在最终程序中包含 foo.a 中的代码,因为 main.o 中没有任何内容引用它。如果main.c改写如下,程序就可以工作了:

//main.c

void foo();

int main()
{
    void (*f)() = foo;
    return 0;
}

此外,当使用静态库进行编译时,gcc(或链接器)的参数顺序很重要:库必须位于引用它的对象之后。

gcc -o test main.o foo.a

【讨论】:

    【解决方案2】:

    如前所述,存档中未引用的符号不会进入输出二进制文件,因为默认情况下链接器会丢弃它们。

    要在与静态库链接时覆盖此行为,可以使用链接器的--whole-archive/--no-whole-archive 选项,如下所示:

    gcc -c main.c
    gcc -c foo.c
    ar rcs foo.a foo.o
    gcc -o test -Wl,--whole-archive foo.a -Wl,--no-whole-archive main.o
    

    这可能会导致二进制文件臃肿,因为来自foo.a 的所有符号都将被链接器包含到输出中,但有时这是合理的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-04-23
      • 2012-01-16
      • 2022-01-06
      • 1970-01-01
      • 2019-03-11
      • 2011-01-04
      • 1970-01-01
      相关资源
      最近更新 更多