web-dev-qa-db-ja.com

共有ライブラリ内の未定義の参照についてGCCに通知する

別の(サードパーティの)共有ライブラリにリンクされている共有ライブラリがあります。次に、アプリケーションでdlopenを使用して共有ライブラリをロードします。これはすべて正常に機能します(ファイルが適切なパスにあると仮定した場合など)。

今、問題は、ライブラリをリンクするときに、サードパーティの共有ライブラリにリンクするように指定する必要さえないことです。 GCCは、未定義の参照に関するエラーを報告せずにそれを受け入れます。だから、質問。 GCCに未定義の参照について通知させるには

ライブラリを(一時的に)実行可能ファイルに変更すると、未定義の参照が得られます(ライブラリをリンカーに提供しない場合)。 (指定すると問題なく動作します。)

つまり、次のことが行われます。

g++ -fPIC -shared -o libb.so b.o 
g++ -fPIC -shared -o liba.so a.o
g++ -o a.exe a.cpp 

2行目はエラーを出さず、3行目は未定義の参照について文句を言います。

サンプルコード:

a.h:

class a
{
public:
    void foobar();
};

a.cpp:

#include "a.h"
#include "b.h"

void a::foobar()
{
    b myB;
    myB.foobar();
}

int main()
{
    a myA; myA.foobar();
}

b.h:

class b
{
public:
    void foobar();
};

b.cpp:

#include "b.h"

void b::foobar()
{
}
48
Fredrik Ullner

-Wl、-no-undefined共有ライブラリを構築するときにリンカーオプションを使用できます。未定義のシンボルはリンカーエラーとして表示されます。

g ++ -shared -Wl、-soname、libmylib.so.5 -Wl、-no-undefined -o libmylib.so.1.1 mylib.o -lthirdpartylib

49
Dmitry Yudakov

さらに調査を重ねた結果、どのように機能するのかがわかりました。共有ライブラリの未定義シンボルを操作するには、2つのリンカーオプションがあります。

最初は--no-undefinedです。リンク段階で、すぐには解決されない未解決のシンボルを報告します。手動で(-lスイッチを使用)または自動(libgcc_s、C++ランタイム、libc、Cランタイム、ld-linux-**.soのいずれかでリンクされた共有ライブラリでシンボルが見つからない場合、動的リンカーutils)が選択され、--no-undefinedはエラーとして報告します。それが質問者が必要とした鍵です。

別のキー--no-allow-shlib-undefinedがあります(その説明は--no-undefinedも示唆しています)。共有ライブラリの定義共有ライブラリのリンク先が満たされているかどうかをチェックします。このキーは、このトピックで示されている場合にはほとんど役に立ちませんが、役に立つ場合があります。ただし、独自の障害があります。

マンページには、デフォルトではない理由についてのいくつかの理論的根拠があります。

   --allow-shlib-undefined
   --no-allow-shlib-undefined
       Allows  (the  default)  or  disallows  undefined  symbols  in  shared
       libraries (It is meant, in shared libraries _linked_against_, not the
       one we're creating!--Pavel Shved). This switch is similar to --no-un-
       defined except  that it determines  the  behaviour when the undefined
       symbols are in a shared library rather than a regular object file. It
       does not  affect  how  undefined  symbols in regular object files are
       handled.

       The  reason  that  --allow-shlib-undefined is the default is that the
       shared library being specified at link time may not be  the  same  as
       the one that is available at load time, so the symbols might actually
       be resolvable at load time.  Plus there are some systems,  (eg  BeOS)
       where  undefined  symbols in shared libraries is normal.  (The kernel
       patches them at load time to select which function is most  appropri-
       ate for the current architecture.  This is used for example to dynam-
       ically select an appropriate memset function).  Apparently it is also
       normal for HPPA shared libraries to have undefined symbols.

上記のことは、たとえば、共有ライブラリの内部ルーチンの一部がld-linux.so(ダイナミックローダー(実行可能ライブラリと共有ライブラリの両方))で実装されているLinuxシステムの場合にも当てはまります。何らかの方法でリンクしない限り、次のようなものが得られます。

/lib64/libc.so.6: undefined reference to `_dl_argv@GLIBC_PRIVATE'
/lib64/libc.so.6: undefined reference to `_rtld_global_ro@GLIBC_PRIVATE'
/usr/lib64/gcc/x86_64-suse-linux/4.3/libstdc++.so: undefined reference to `__tls_get_addr@GLIBC_2.3'
/lib64/libc.so.6: undefined reference to `_rtld_global@GLIBC_PRIVATE'
/lib64/libc.so.6: undefined reference to `__libc_enable_secure@GLIBC_PRIVATE'

これらは、ローダーld-linux.soからの未定義の参照です。プラットフォーム固有です(たとえば、私のシステムでは、正しいローダーは/lib64/ld-linux-x86-64.soです)。ローダーをライブラリにリンクし、上記のトリッキーなリファレンスを確認することもできます。

g++ -fPIC -shared -o liba.so a.o -Wl,--no-allow-shlib-undefined  /lib64/ld-linux-x86-64.so.2
17
P Shved

Ld(gccが実行しているもの)がリンクにないライブラリに注意を払うことはできません。 RTLD_LAZYをオフにして積極的なレポートを取得し、リンクの直後に実行される単体テストを追加して、これらの問題を洗い流すことができます。

1
bmargulies