¿Por qué no funciona __attribute __ ((constructor)) en una biblioteca estática?
-
05-07-2019 - |
Pregunta
En el siguiente ejemplo, el programa debería imprimir " foo llamado " ;:
// foo.c
#include <stdio.h>
__attribute__((constructor)) void foo()
{
printf("foo called\n");
}
// main.c
int main()
{
return 0;
}
Si el programa se compila así, funciona:
gcc -o test main.c foo.c
Sin embargo, si foo.c se compila en una biblioteca estática, el programa no imprime nada.
gcc -c main.c
gcc -c foo.c
as rcs foo.a foo.o
gcc -o test foo.a main.o
¿Por qué sucede esto?
Solución
El enlazador no incluye el código en foo.a en el programa final porque nada en main.o lo referencia. Si main.c
se reescribe de la siguiente manera, el programa funcionará:
//main.c
void foo();
int main()
{
void (*f)() = foo;
return 0;
}
Además, al compilar con una biblioteca estática, el orden de los argumentos para gcc (o el vinculador) es significativo: la biblioteca debe ir después de los objetos que la referencian.
gcc -o test main.o foo.a
Otros consejos
Como se indicó, los símbolos no referenciados del archivo no llegan al binario de salida, porque el vinculador los descarta de forma predeterminada.
Para anular este comportamiento cuando se vincula con una biblioteca estática, se pueden usar las opciones --whole-archive
/ --no-whole-archive
para el enlazador, como este :
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
Esto puede llevar a un binario inflado, porque el vinculador incluirá todos los símbolos de foo.a
en la salida, pero a veces está justificado.