typeinfo,共享库和dlopen(),而不使用RTLD_GLOBAL [英] typeinfo, shared libraries and dlopen() without RTLD_GLOBAL

查看:963
本文介绍了typeinfo,共享库和dlopen(),而不使用RTLD_GLOBAL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在遇到一些异常无法正常工作(或至少,我希望;我知道这是有问题)跨共享库加载时使用> dlopen 。我在这里包括一些简化的示例代码。实际情况是myapp = Matlab, myext1 = mexglx matlab扩展, mylib 是两个扩展之间的代码共享库( > myext1 myext2

I'm having some trouble with exceptions not functioning correctly (or at least, as I would hope; I know there are issues with this) across shared libraries when loaded using dlopen. I include some simplified example code here. The actual situation is myapp=Matlab, myext1=mexglx matlab extension, mylib is a shared library of my code between the two 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 与myext1.cpp相同

myext2.cpp Identical to 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()按预期工作,抛出异常,并且 entrypoint()捕获它。但是,在 B 处的呼叫无法捕获异常。添加更多诊断代码显示,在这两个扩展中, Foo 类的typeinfo不同。更改两个dlopen调用的顺序没有区别,第二个加载的扩展失败。

The call to entrypoint() at A works as expected, with throwFoo() throwing the exception and entrypoint() catching it. The call at B however fails to catch the exception. Adding more diagnostic code shows that the typeinfo for the Foo class differs in the two extensions. Changing the order of the two dlopen calls makes no difference, the second loaded extension fails.

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

I know I can fix this by using RTLD_GLOBAL as an additional flag for dlopen, but the application (Matlab) using dlopen is out of my control. Is there anything I can do with mylib or myext1, myext2 to fix this problem?

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

I have to avoid using LD flags for runtime (since I cannot control the users running the Matlab binary). Any other suggestions?

推荐答案

Alexandre C&C的C ++编码标准 Sutter:

Rule 62 in "C++ Coding Standards" by Alexandrescu & Sutter:

62。不允许异常传播跨模块边界。

"62. Don’t allow exceptions to propagate across module boundaries."

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

Although it can work when you do it carefully, for true portable and reusable code, this cannot be done. I would say it is a pretty common general rule when programming shared libraries or DLLs, do not propagate exceptions across module boundaries. Just use a C-style interface, return error codes, and do everything inside an exported function inside a try { } catch(...) { }; block. Also, the RTTI is not shared across modules, so don't expect Foo to have the same typeinfo in different modules.

这篇关于typeinfo,共享库和dlopen(),而不使用RTLD_GLOBAL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆