首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >C++力卸载共享库

C++力卸载共享库
EN

Stack Overflow用户
提问于 2016-06-08 22:12:54
回答 2查看 2.6K关注 0票数 9

我正在尝试创建一个多次重新加载共享库的应用程序。但是在某个时候,dlmopen失败了

/usr/lib/libc.so.6: cannot allocate memory in static TLS block

下面是再现此问题的最小代码:

代码语言:javascript
运行
复制
#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;
}

和空的lib.cpp,用

代码语言:javascript
运行
复制
g++ -rdynamic -ldl -Wl,-R . -o test main.cpp
g++ -fPIC -shared lib.cpp -o lib.so

更新

看起来,即使只有一个线程,它也会崩溃。问题是:如何强制库卸载或破坏使用LM_ID_NEWLM创建的未使用的命名空间?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-01-11 09:20:03

对于一个进程可用的链接映射命名空间的数量有一个内置限制。这一点在评论中记录得相当少:

glibc实现最多支持16个命名空间。

在手册页上。

一旦创建了链接映射命名空间,就不支持通过任何API“擦除”它。这正是它的设计方式,如果不编辑glibc源代码和添加一些钩子,就没有真正的解决方法。

使用名称空间来重新加载库实际上并不是重新加载库--您只是加载库的一个新副本。这是名称空间的用例之一--如果您多次尝试使用同一个库,您将得到同一个库的同一个句柄;但是,如果您将第二个实例加载到不同的名称空间中,则不会得到相同的句柄。如果要完成重新加载,则需要使用dlclose卸载库,一旦释放了对库的最后剩余引用,库将卸载。

如果您想要“强制卸载”一个库,那么您可以尝试发出多个dlclose调用,直到它卸载为止;但是,如果您不知道库做了什么(例如生成线程),那么在这种情况下可能无法防止崩溃。

票数 2
EN

Stack Overflow用户

发布于 2017-01-10 10:26:44

较早的glibc版本可能存在一些与此相关的bug:

bug.cgi?id=89692 bug.cgi?id=14898

你用的是什么版本?尝试使用更新的glibc版本,您的代码在我的计算机上运行得很好(glibc 2.23)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37713826

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档