Почему __attribute __ ((конструктор)) не работает в статической библиотеке? - PullRequest
27 голосов
/ 29 июля 2009

В следующем примере программа должна вывести «foo named»:

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

14 голосов
/ 29 июля 2009

Компоновщик не включает код в 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
5 голосов
/ 30 марта 2016

Как было указано, символы из архива, на которые нет ссылок, не попадают в выходной двоичный файл, поскольку компоновщик по умолчанию отбрасывает их.

Чтобы переопределить это поведение при связывании со статической библиотекой, можно использовать опции --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 будут включены компоновщиком в вывод, но иногда это оправдано.

...