5

gcc リンクの順序についていくつか質問があります。GCC man は、リンカがデフォルトで繰り返し検索せずにシンボルを左から右に検索すると言います。これが私のテストです:

main.c

#include <stdio.h>
#include <stdlib.h>

int main()
{
        printf("HELLO WROLD\n");
        return 0;
}

printfc.c

#include <stdio.h>
#include <stdlib.h>

int printf(const char *fmt, ...)
{
        write(1, "AAA\n", 4);
}

[root@lenovo testcode]# gcc -c -fno-builtin-printf *.c
[root@lenovo testcode]# gcc -o test main.o printf.o
[root@lenovo testcode]# ./test 
AAA
[root@lenovo testcode]# gcc -o test printf.o main.o
[root@lenovo testcode]# ./test
AAA


[root@lenovo testcode]# ar rcs libprintf.a printf.o
[root@lenovo testcode]# gcc -o test libprintf.a main.o
[root@lenovo testcode]# ./test 
HELLO WROLD
[root@lenovo testcode]# gcc -o test main.o libprintf.a 
[root@lenovo testcode]# ./test 
AAA


[root@lenovo testcode]# gcc -shared -o libprintf.so printf.o 
[root@lenovo testcode]# gcc -o test libprintf.so  main.o 
[root@lenovo testcode]# export LD_LIBRARY_PATH=.
[root@lenovo testcode]# ./test 
AAA
[root@lenovo testcode]# gcc -o test main.o libprintf.so 
[root@lenovo testcode]# ./test 
AAA

結果から、.o と .o の順序、.o と .so は違いがなく、.o と .a の順序のみが効果があることがわかります。しかし、それは gcc の man ページと矛盾しています。なぜ?

4

1 に答える 1

8

実際、gcc はオブジェクト ファイルを左から右に処理します。あなたが持っているとき

gcc -o test libprintf.a main.o

gcc が最初に認識するオブジェクト ファイルはlibprintf.a. この時点で出力オブジェクトの未解決のシンボルはないため、何もlibprintf.a使用/必要ありません。次にmain.o処理され、リンカは未解決の事実を記録し、未解決のシンボルprintfを解決できる暗黙的なライブラリの処理に進みます。printfin main.o

同様に、次の場合:

gcc -o test main.o libprintf.a 

最初に処理されるオブジェクト ファイルはmain.oで、未解決のシンボルprintfが示されています。次に処理されるのはlibprintf.a、リンカーが解決できるファイルですprintf。Whenlibcは最終的に処理され、既に解決されているため、 inprintfのインスタンスは使用されません。printflibc

.o ファイルとリンクする場合:

gcc -o test main.o printf.o

ライブラリは、コマンド ラインの最後で指定されたかのlibcように再び扱われるため、printfシンボルはそれを定義する最初の (左から右へ) オブジェクト ファイルから解決されます。

どちらのlibprintf.so場合も、libcライブラリはコマンド ラインの最後で指定されたかのように扱われます。静的ライブラリの場合と異なる点は、ライブラリの左から右への順序*.soによって、実行時の動的シンボル検索順序が決定されることです。この順序はlibprintf.so暗黙の の前にあるため、 inlibc.soのバージョンが使用されます。printflibprintf.so

gcc -o test libprintf.so  main.o
gcc -o test main.o libprintf.so

追加の実験として、次のことを試すことができます。

gcc -o test main.o -lc libprintf.so

これは、左から右の順序で前に来るので、代わりにprintf使用されている fromのバージョンを表示する必要があります。libc.solibprintf.so-lclibprintf.so

于 2012-05-14T16:27:11.797 に答える