c++ - typeinfo, shared libraries and dlopen() without RTLD_GLOBAL -
i'm having trouble exceptions not functioning correctly (or @ least, hope; know there issues this) across shared libraries when loaded using dlopen. include simplified example code here. actual situation myapp=matlab, myext1=mexglx matlab extension, mylib shared library of code between 2 extensions (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 identical 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) }
compiling code:
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
the call entrypoint() @ a works expected, throwfoo() throwing exception , entrypoint() catching it. call @ b fails catch exception. adding more diagnostic code shows typeinfo foo class differs in 2 extensions. changing order of 2 dlopen calls makes no difference, second loaded extension fails.
i know can fix using rtld_global additional flag dlopen, application (matlab) using dlopen out of control. there can mylib or myext1, myext2 fix problem?
i have avoid using ld flags runtime (since cannot control users running matlab binary). other suggestions?
rule 62 in "c++ coding standards" alexandrescu & sutter:
"62. don’t allow exceptions propagate across module boundaries."
although can work when carefully, true portable , reusable code, cannot done. pretty common general rule when programming shared libraries or dlls, not propagate exceptions across module boundaries. use c-style interface, return error codes, , inside exported function inside try { } catch(...) { };
block. also, rtti not shared across modules, don't expect foo have same typeinfo in different modules.
Comments
Post a Comment