33

在以下示例中,程序应打印"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

为什么会这样?

4

2 回答 2

18

链接器不会在最终程序中包含 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
于 2009-07-29T19:30:42.073 回答
8

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

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

于 2016-03-30T04:09:49.757 回答