3

私は次のCファイルを持っています:

Base.h:

void g();
void h();

Base.c:

#include <stdio.h>
#include <Base.h>

void g() {
  printf("This is lib g\n");
  h();
}

void h() {
  printf("This is lib h\n");
}

交流:

#include <stdio.h>
#include <Base.h>

void h() {
  printf("This is A h\n");
}

void main() {
  g();
  h();
}

私は次のようにコンパイルしてリンクします:

$ gcc -c -fPIC -o Base.o -I. Base.c
$ gcc -shared -o libBase.so Base.o
$ gcc -c -o A.o A.c
$ gcc -o A A.o -lBase -L.

今、私はプログラムを実行します

$ LD_LIBRARY_PATH=. ./A

取得します:

This is lib g
This is A h
This is A h

つまり、libBaseでのhの呼び出しは、Aoのhによって解決されます。これは私が期待したものではありません。ダイナミックリンカがlibBaseのhへの呼び出しをlibBaseのhで解決するか、4番目のgcc呼び出しでエラーメッセージを解決することを期待していました。

Acのhの名前をh1に変更すると

#include <stdio.h>
#include <Base.h>

void h1() {
  printf("This is A h1\n");
}

void main() {
  g();
  h1();
}

取得します

This is lib g
This is lib h
This is A h1

したがって、この場合、hは予想どおりに解決されます。

エラーメッセージを取得するか、gの呼び出しをlibBaseのhに解決するにはどうすればよいですか?

4

1 に答える 1

2

これは私が期待したものではありません。

あなたの期待は間違っています。これは、ほとんどのUNIXシステムの共有ライブラリが機能する方法です。ローダーは、ロードされたライブラリのリストを下に移動し、指定されたシンボルを見つけようとします。シンボルを定義する最初のライブラリが「勝ち」ます。

この動作には多くの利点があります。一例:あなたはできますLD_PRELOAD libtcmalloc.so、そして突然すべてmallocfree呼び出しはに解決しtcmallocます。

-BsymbolicELFシステムでは、リンカーフラグを使用してこの動作を変更できます( -Wl,-BsymbolicGCCを通過するときに使用します)。注意:-Bsymbolic「システムに対して」実行すると、結果として多くの予期しない望ましくない副作用が発生する可能性があります。

この回答も参照してください。

于 2012-10-26T02:09:36.180 に答える