dlopen不尊重`RTLD_LOCAL`吗?

col*_*ang 4 linux glibc shared-libraries dlopen

我有A.so,它链接到libstdc++.so.6在其自己的目录中的特定版本(通过rpath设置为$ORIGIN)。

如果我dlopen A.so一个人,那就很好。

如果dlopen我的系统libstdc++.so.6(版本不同)处于RTLD_LOCAL模式,然后dlopen A.so

OSError: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.20' not found (required by A.so)
Run Code Online (Sandbox Code Playgroud)

为什么dlopen不尊重RTLD_LOCAL

Emp*_*ian 8

为什么不公开尊重 RTLD_LOCAL

RTLD_LOCAL并不代表您的意思。来自man dlopen

RTLD_LOCAL
          This is the converse of RTLD_GLOBAL, and the default if
          neither flag is specified.  Symbols defined in this shared
          object are not made available to resolve references in
          subsequently loaded shared objects.
Run Code Online (Sandbox Code Playgroud)

请注意,这没有说明加载程序正在加载哪个库。

装载程序将永远载入给定的多个实例SONAME(除非你使用使用不同的连接范围dlmopen),所以当你dlopen的系统libstdc++.so.6,这是唯一的 libstdc++.so.6,你会永远得到。稍后dlopen("A.so", ...),运行时加载程序:

  1. 查找,图书馆A.so依赖,发现libstdc++.so.6在其中,并发现它已经已经libstdc++.so.6加载,所以也没有搜索,也没有加载另一个副本,
  2. 查找所需的版本符号A.so。正是在这一点上,您收到错误,因为从中A.so需要,并且由于已经加载的系统较旧并且不提供版本。GLIBCXX_3.4.20libsstdc++.so.6libstdc++.so.6GLIBCXX_3.4.20
  3. 由于第2步失败,您的dlopen被拒绝。

请注意,您永远不会从中解析任何符号libstdc++.so.6(重要的地方RTLD_LOCAL);之前你就失败了。

现在,您可能正在尝试进行构建A.so,以使其可以动态加载到任意程序中(可能使用较旧版本的程序)libstdc++.so.6,而不必强迫最终用户更新系统libstdc++.so.6。不幸的是,这根本无法完成。

  • 关于您的最后一段,为什么 dlmopen() 不能做到这一点?显然,您不能通过接口传递 STL 类型(即在使用 libstdc++.so 的不同实例的代码之间),但它不能在库中用于私人用途吗? (2认同)