2

関数シンボルの競合の問題をデバッグすると、理解できない gcc の奇妙な動作が見つかりました。次のサンプル コードで説明します。

main.c

#include <stdio.h>
int  main()
{
   b();
   a();
}

交流

#include <stdio.h>
void  a(void)
{
   printf("func a in a\n");
}

紀元前

#include <stdio.h>

void a()
{
   printf("func a in b\n");
}
void b()
{
  printf( "func b try to call a  \n");
  a();
}

コンパイル:

gcc -c a.c
gcc -c b.c
ar -cr liba.a a.o
ar -cr libb.a b.o
gcc main.c liba.a libb.a

実行する:

./a.out
func b try to call a  
func a in b
func a in b   

私の質問は:

  • a関数内でmain関数をa in b.c呼び出すのはなぜa in a.cですか?
  • ライブラリの順序を変更した後: gcc main.c libb.a liba.a、結果は同じです。なんで?
  • この状況でリンカーがシンボルの競合を報告しないのはなぜですか?
4

2 に答える 2

1

オブジェクト ファイルは、リンカに渡されたオプションで左から右へ、オブジェクト ファイルの外観の順序で解決されるシンボルを検索されます。

リンクの準備として、次のものが実行されていると仮定します。

gcc -c main.c
gcc -c a.c
gcc -c b.c
ar -cr liba.a a.o
ar -cr libb.a b.o

それからこれ

gcc -o main main.o liba.a libb.a

生成されます:

libb.a(b.o): In function `a':
b.c:(.text+0x0): multiple definition of `a'
liba.a(a.o):a.c:(.text+0x0): first defined here
collect2: ld returned 1 exit status

リンカーは次のことを行いました。

main.oニーズa()b ()。最初libaに検索されます:a()見つかった、見つかりb()ませんでした。2番目libbに検索されます。b()が見つかりましたが、上記のリンカ エラーにつながる別のエラーも発生しています。 a()

行う場合:

gcc -o main main.o libb.a liba.a

エラーは発生せず、main作成されます。

リンカーは次のことを行いました。

main.oニーズa()b ()。最初libbに検索されます: a()and b()are が見つかります。もう解決することは何もないので、見たり調べたりすることさえありません。libb liba

後者の場合、プログラムの (mainの) 出力は次のようになります。

func b try to call a  
func a in b
func a in b

の他のすべての可能な順列に対してリンカが行う/表示することはmain.o、読者への演習として残されていますliba.alibb.a;-)

于 2013-09-01T09:24:55.067 に答える
1

aにおよびb関数宣言を含めていませんmain.c。その場合、リンカーに渡される前に、コンパイラから複数の宣言エラーが発生します。で何か間違ったことをしているに違いありませんmain.c

于 2013-09-01T05:42:21.040 に答える