dlopenを使用してロードしたときに、共有ライブラリ全体で例外が正しく機能しないという問題があります (または、少なくとも、期待どおりです。これには問題があることはわかっています) 。ここにいくつかの単純化されたサンプル コードを含めます。実際の状況はmyapp =Matlab, myext1 =mexglx matlab 拡張機能です。mylibは 2 つの拡張機能 ( myext1、myext2 )間の私のコードの共有ライブラリです。
mylib.h
struct Foo { Foo(int a); m_a; }
void throwFoo();
mylib.cpp
#include "mylib.h"
Foo::Foo(int a): m_a(a) {}
void throwFoo() { throw Foo(123); }
myext1.cpp
#include "mylib.h"
#include <iostream>
extern "C" void entrypoint()
{
try { throwFoo(); }
catch (Foo &e) { std::cout << "Caught foo\n"; }
}
myext2.cpp myext1.cppと同じ
myapp.cpp
#include <dlfcn.h>
int main()
{
void *fh1 = dlopen("./myext1.so",RTLD_LAZY);
void *fh2 = dlopen("./myext2.so",RTLD_LAZY);
void *f1 = dlsym(fh1,"entrypoint");
void *f2 = dlsym(fh2,"entrypoint");
((void (*)())func1)(); // call myext1 (A)
((void (*)())func2)(); // call myext2 (B)
}
このコードのコンパイル:
g++ mylib.cpp -fPIC -o libmylib.so -shared
g++ myext1.cpp -fPIC -o myext1.so -shared -L. -lmylib -Wl,-rpath=.
g++ myext2.cpp -fPIC -o myext2.so -shared -L. -lmylib -Wl,-rpath=.
g++ myapp.cpp -fPIC -o myapp -ldl
Aでの entrypoint( )の呼び出しは期待どおりに機能し、throwFoo()が例外をスローし、 entrypoint( )が例外をキャッチします。ただし、 Bでの呼び出しは例外をキャッチできません。さらに診断コードを追加すると、 Fooクラスの typeinfo が2 つの拡張機能で異なることがわかります。2 つのdlopen呼び出しの順序を変更しても違いはなく、2 番目にロードされた拡張機能は失敗します。
RTLD_GLOBALをdlopenの追加フラグとして使用することでこれを修正できることはわかっていますが、 dlopen を使用するアプリケーション (Matlab) は制御できません。この問題を解決するためにmylibまたはmyext1、myext2でできることはありますか?
実行時に LD フラグを使用しないようにする必要があります (Matlab バイナリを実行しているユーザーを制御できないため)。他の提案はありますか?