为什么__attribute __((构造函数))在静态库中不起作用?

时间:2009-07-29 19:27:11

标签: c constructor attributes static-libraries

在以下示例中,程序应打印“foo called”:

// 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

为什么会这样?

2 个答案:

答案 0 :(得分:14)

链接器在最终程序中不包含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

答案 1 :(得分:5)

如上所述,来自存档的未引用符号不会使其成为输出二进制文件,因为链接器默认会丢弃它们。

要在与静态库链接时覆盖此行为,可以使用链接器的--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中的所有符号都包含在输出中,但有时它是合理的。