別の(サードパーティの)共有ライブラリにリンクされている共有ライブラリがあります。次に、アプリケーションで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()
{
}
-Wl、-no-undefined共有ライブラリを構築するときにリンカーオプションを使用できます。未定義のシンボルはリンカーエラーとして表示されます。
g ++ -shared -Wl、-soname、libmylib.so.5 -Wl、-no-undefined -o libmylib.so.1.1 mylib.o -lthirdpartylib
さらに調査を重ねた結果、どのように機能するのかがわかりました。共有ライブラリの未定義シンボルを操作するには、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
Ld(gccが実行しているもの)がリンクにないライブラリに注意を払うことはできません。 RTLD_LAZYをオフにして積極的なレポートを取得し、リンクの直後に実行される単体テストを追加して、これらの問題を洗い流すことができます。