背景: 他の独立したアプリケーションのライブラリとして使用されるアプリケーションがあります。それらはリンク時にそのライブラリにリンクします(lib.soと言うことができます)。そのようなアプローチの問題は、boost、aceなどのような同じ外部ライブラリを使用する必要があるか、または最終的にクラッシュを引き起こす重複したシンボルを持つことになります。この問題を解決したい。共有ライブラリのRTLD_DEEPBINDによる動的ロード
私は2つの手法を知っています.1つはすべてのシンボル(共有ライブラリのスコープのグローバル/ローカルのオーダーについてはわかりません)を隠す方法と、動的リンクを使用する方法です。スタブ付きのlib.soで簡単にテストできるようにするため、2番目のオプション(動的リンク)を選択しました。我々は非常に単純なAPIを持っています。
以下の例は、共有ライブラリのサンプルをロードしてクラッシュするアプリケーションの小さな例です(クラッシュした理由と書き込み方法を理解したいと思います)。 クラッシュはdlopenにあります。つまり、std :: string(Aclass型のコンストラクタ)への代入時にグローバル変数が初期化されます。私たちのテストでは、ライブラリの初期化中にクラッシュすることになるので、stdライブラリへのアクセスはすべて見えます。
EXECUTABLEに-fPICフラグを追加することでクラッシュを取り除くことができました(私たちの問題を解決した理由は、共有ライブラリに設定する必要があると思います。私の理解に不必要なのは、このフラグはアプリケーションの処理速度が遅いために問題があり、私の場合(低レイテンシのアプリケーション)はかなり問題です。
概要: 1.なぜこのクラッシュが発生するのですか? 2.なぜこのクラッシュを解決するには-fPICフラグで十分ですか? 3. -fPICフラグを実行可能に設定するだけで十分なのはなぜですか? 4.他の方法で私の問題を解決することは可能ですか?共有ライブラリとクライアントアプリケーションは異なるバージョンのライブラリを使用できますか?(boost、aceなどのコンパイラ、Linuxのバージョンと標準ライブラリは同じであることが保証されます) 5.フラグRTLD_DEEPBINDを削除するとクラッシュも修正されますが、gcc manからは共有ライブラリのシンボルスコープの順序が変更されるので、このフラグを使用する必要があります - まずローカルスコープ内のシンボルをグローバルで検索します私は共有ライブラリとして、実行可能ファイルとは異なる外部ライブラリを使用します(動的ロードは実行可能ファイルをそのシンボルスコープを汚染して保護します)。この単純なケースでこのフラグを削除するとクラッシュが解決されるのはなぜですか?
共有ライブラリdynLib.cpp:
#include <string>
class Aclass
{
std::string s;
s = "123";
}
Aclass a;
Exacutable main.cppに:
#include <stdlib.h>
#include <dlfcn.h>
#include <string>
#include <unistd.h>
#include <iostream>
int main()
{
std::string dummyCrasher;
dlerror();
void* handle = dlopen("./libdynLib.so", RTLD_LAZY | RTLD_LOCAL | RTLD_DEEPBIND);
if(!handle)
{
std::cout << "handle is null" << dlerror();
}
usleep(1000 * 1000 * 10);
}
のMakefile:メイク
CXXFLAGS=-m32 -march=x86-64 -Wl,v -g -O3 -Wformat -Werror=format -c
CLINKFLAGS=-Wl,-Bstatic -Wl,Bdynamic -ldl -m32 -march=x86-64
all: dynLib.so dynamiclinking
dynLib.so: dynLib.o
g++44 $(CLINKFLAGS) -shared -o libdynLib.so dynLib.o
dynLib.o: dynLib.cpp
g++44 $(CXXFLAGS) dynLib.cpp
dynamiclinking: main.o
g++44 $(CLINKFLAGS) -o dynamiclinking main.o -ldl
main.o: main.cpp
g++44 (CXXFLAGS) main.cpp
.PHONY: clean
clean:
rm dynLib.o main.o dynamiclinking libdynLib.so
PS。のlibstdC++の静的結合によってこの問題を解決することが可能であるUPDATE
main.o: main.cpp
g++44 (CXXFLAGS) main.cpp -fPIC
:私は(一部のスペルミスをした可能性が)手でそれが動作します-fPICフラグと PS 2.そのコードを記述します。しかし、まだ私の質問には答えていない:(たぶん、誰かがそれを見ていくつかの時間を持っている?
アップデート2同じ問題がGCC 4.4.6および4.8.1で発生します。
私は最近同様の問題があり、このバグレポートを見つけました:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=42679これは完全な解決策ではありませんが、問題の洞察少なくとも。 – Filip