programing

정적 라이브러리에서 __attribute__((구성자))가 작동하지 않는 이유는 무엇입니까?

bestprogram 2023. 10. 4. 22:15

정적 라이브러리에서 __attribute__((구성자))가 작동하지 않는 이유는 무엇입니까?

다음 예제에서 프로그램은 인쇄해야 합니다."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

그러나 fo.c가 정적 라이브러리로 컴파일되면 프로그램은 아무것도 인쇄하지 않습니다.

gcc -c main.c
gcc -c foo.c
as rcs foo.a foo.o
gcc -o test foo.a main.o

왜 이런 일이 일어날까요?

링커는 fo.a의 코드를 포함하지 않습니다. 왜냐하면 main.o의 어떤 것도 그것을 참조하지 않기 때문입니다. 만약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링커에 의해 출력에 포함되지만 정당화되는 경우도 있습니다.

언급URL : https://stackoverflow.com/questions/1202494/why-doesnt-attribute-constructor-work-in-a-static-library