dlmopen 可以用作 dlopen 的“直接”替代品吗?

问题描述 投票:0回答:1

我有一个非线程安全的共享库(C/Fortran),即它使用全局变量定义其状态。因此,当我使用 dlopen 从同一进程多次打开该库时,全局变量是共享的,即状态会受到干扰(混乱),因为仅增加了引用计数。 (当我 dlopen 库的两个物理副本时,我的应用程序可以正常工作。)。

我发现上面链接的问题和另一个提到 dlmopen 的问题表明我can加载库的单独实例(带有它们自己的全局变量),这将消除问题。 dlmopen 的文档对我来说很难理解,但我尝试了一下并尝试用这样的东西打开我的库:

inline handle_type open(std::string const& filename) {
    handle_type h = dlmopen(LM_ID_NEWLM, filename.c_str(), RTLD_LAZY);
    return h;
}

但是,唉,我遇到了一次崩溃,valgrind 报告从我的代码中一个奇怪的(看似无辜的)位置读取了大小为 32 的无效读取(位于 0x2833DE35:???(在 /usr/lib64/libc-2.28.so 中)) (

a = &static_function;
),即将静态函数的地址分配给某个函数指针。

所以我的问题是:库的一份副本上的 dlmopen 是否应该与两份副本上的 dlopen 得到相同的结果?我是否以错误的方式调用 dlmopen ?或者当我使用 dlmopen 时分配静态函数的地址是否存在根本问题?

c++ shared-libraries posix dlopen
1个回答
0
投票

所以我的问题是:库的一份副本上的 dlmopen 是否应该与两份副本上的 dlopen 得到相同的结果?

不一定1.

我调用 dlmopen 的方式是否错误?

我建议使用

RTLD_NOW
而不是
RTLD_LAZY

如果您这样做,并且

dlmopen
调用没有失败(不返回
NULL
),然后您可以得出结论,该库已与其所有依赖项正确链接。

如果

dlmopen(..., RTLD_NOW)
失败,您可以断定在此库上使用
dlmopen
不起作用。


如果

dlmopen
应该 有效,您的下一个任务就是找出崩溃的原因。不幸的是,用于调试的工具支持几乎不存在。例如,Valgrind 很可能会完全混乱。

可能能够使用GDB来理解崩溃,但即使这样也可能需要手动告诉GDB新添加的库所在的位置(请参阅this错误)。注意:该错误已修复,因此最新版本的 GDB 可能可以正常工作。

或者当我使用 dlmopen 时分配静态函数的地址是否存在根本问题?

没有。


1 有很多差异。作为一个示例,考虑一下当您调用此库中的函数(例如

foo()
)时会发生什么,该函数返回用
malloc
分配的内存,并且您负责
free
ing。当使用单个链接器命名空间时,图中只有一个
malloc
,一切正常。

当你

dlmopen
图书馆两次时,就有三个!
malloc
的实例(一个位于默认命名空间中,两个位于两个新命名空间中)。如果您现在将由
malloc
的一个实例分配的指针传递给位于另一命名空间中的
free
,则可能会发生崩溃或堆损坏。

© www.soinside.com 2019 - 2024. All rights reserved.