静的ライブラリで__attribute __((constructor))が機能しないのはなぜですか?
-
05-07-2019 - |
質問
次の例では、プログラムは" 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
なぜこれが起こるのですか?
解決
リンカは、main.oに何も参照しないため、foo.aのコードを最終プログラムに含めません。 main.c
が次のように書き換えられた場合、プログラムは動作します:
//main.c
void foo();
int main()
{
void (*f)() = foo;
return 0;
}
また、静的ライブラリでコンパイルする場合、gcc(またはリンカー)への引数の順序は重要です。ライブラリは、それを参照するオブジェクトの後に来る必要があります。
gcc -o test main.o foo.a
他のヒント
前述のように、アーカイブからの参照されていないシンボルは、デフォルトでリンカーによって破棄されるため、出力バイナリにはなりません。
静的ライブラリとリンクするときにこの動作をオーバーライドするには、次のように、リンカーの-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
からのすべてのシンボルがリンカーによって出力に含まれるので、肥大化したバイナリにつながる可能性がありますが、正当化される場合もあります。
所属していません StackOverflow