静的ライブラリで__attribute __((constructor))が機能しないのはなぜですか?

StackOverflow https://stackoverflow.com/questions/1202494

質問

次の例では、プログラムは" 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 からのすべてのシンボルがリンカーによって出力に含まれるので、肥大化したバイナリにつながる可能性がありますが、正当化される場合もあります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top