Ily*_*nov 8 c++ linux shared-libraries
我正在尝试创建一个多次重新加载共享库的应用程序.但在某个时间点,dlmopen失败并出现错误
/usr/lib/libc.so.6: cannot allocate memory in static TLS block
以下是重现此问题的最小代码:
#include <dlfcn.h>
#include <cstdio>
#include <vector>
int main() {
for (int i = 0; i < 100; ++i) {
void *lib_so = dlmopen(LM_ID_NEWLM, "lib.so", RTLD_LAZY | RTLD_LOCAL);
if (lib_so == NULL) {
printf("Iteration %i loading failed: %s\n", i, dlerror());
return 1;
}
dlclose(lib_so);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
并清空lib.cpp,用.编译
g++ -rdynamic -ldl -Wl,-R . -o test main.cpp
g++ -fPIC -shared lib.cpp -o lib.so
Run Code Online (Sandbox Code Playgroud)
它似乎即使用一个线程也会崩溃.问题是:如何强制库卸载或销毁使用的未使用的命名空间LM_ID_NEWLM?
进程可用的链接映射命名空间的数量存在内置限制。评论中对此的记录相当少:
glibc 实现最多支持 16 个命名空间
在手册页中。
创建链接映射命名空间后,将不支持通过任何 API“删除”它。这就是它的设计方式,如果不编辑 glibc 源代码并添加一些钩子,就没有真正的方法可以解决这个问题。
使用名称空间重新加载库实际上并不是重新加载库 - 您只是加载库的新副本。这是命名空间的用例之一 - 如果您dlopen多次尝试使用同一个库,您将获得同一个库的相同句柄;但是,如果您在不同的命名空间中加载第二个实例,您将不会获得相同的句柄。如果要完成重新加载,则需要使用 卸载库dlclose,一旦释放了对库的最后一个剩余引用,就会卸载库。
如果您想尝试“强制卸载”库,那么您可以尝试发出多个dlclose调用,直到它卸载;但是,如果您不知道库做了什么(例如生成的线程),那么在这种情况下可能无法防止崩溃。
| 归档时间: |
|
| 查看次数: |
1333 次 |
| 最近记录: |