c – typeinfo,共享库和没有RTLD_GLOBAL的dlopen()

前端之家收集整理的这篇文章主要介绍了c – typeinfo,共享库和没有RTLD_GLOBAL的dlopen()前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一些麻烦,异常不能正常工作(或至少,因为我希望;我知道这是有问题)跨共享库加载时使用dlopen.我在这里包括一些简化的示例代码.实际情况是myapp = Matlab,myext1 = mexglx matlab扩展,mylib是我的代码在两个扩展之间的共享库(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在两个扩展中不同.更改两个dlopen呼叫的顺序没有任何区别,第二个加载的扩展失败.

我知道我可以通过使用RTLD_GLOBAL作为dlopen的附加标志来解决这个问题,但是使用dlopen的应用程序(Matlab)无法控制.有什么我可以用mylib或myext1,myext2来解决这个问题吗?

我必须避免使用LD标志来运行(因为我无法控制运行Matlab二进制文件用户).任何其他建议?

解决方法

Alexandrescu& C“C编码标准”第62条萨特:

“62.不允许异常传播跨模块边界.”

虽然它可以工作,当你仔细地做,为真正的便携和可重用的代码,这是不能做到的.我会说,编程共享库或DLL时,这是一个很常见的一般规则,不会跨模块边界传播异常.只需使用C风格的界面,返回错误代码,并在try {} catch(…){}中的导出函数内部执行所有操作.块.此外,RTTI不是跨模块共享的,所以不要指望Foo在不同的模块中具有相同的typeinfo.

猜你在找的C&C++相关文章