gpt4 book ai didi

c++ - 没有 RTLD_GLOBAL 的类型信息、共享库和 dlopen()

转载 作者:可可西里 更新时间:2023-11-01 16:05:56 26 4
gpt4 key购买 nike

当使用 dlopen 加载共享库时,我遇到了一些异常无法正常运行的问题(或者至少,正如我所希望的那样;我知道这有问题)。我在这里包含了一些简化的示例代码。实际情况是myapp=Matlab,myext1=mexglx matlab extension,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 类的类型信息在两个扩展中不同。更改两个 dlopen 调用的顺序没有区别,第二个加载的扩展失败。

我知道我可以通过使用 RTLD_GLOBAL 作为 dlopen 的附加标志来解决这个问题,但是使用 dlopen 的应用程序 (Matlab) 不在我的控制范围内。我可以用 mylibmyext1myext2 做些什么来解决这个问题吗?

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

最佳答案

Alexandrescu 和 Sutter 的“C++ 编码标准”中的规则 62:

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

虽然当你小心的时候它可以工作,但是对于真正的可移植和可重用的代码,这是不可能做到的。我会说,在对共享库或 DLL 进行编程时,这是一个非常普遍的一般规则,不要跨模块边界传播异常。只需使用 C 风格的接口(interface),返回错误代码,并在 try { } catch(...) { }; block 内的导出函数内执行所有操作。此外,RTTI 不会跨模块共享,因此不要指望 Foo 在不同模块中具有相同的类型信息。

关于c++ - 没有 RTLD_GLOBAL 的类型信息、共享库和 dlopen(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5044993/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com