【发布时间】:2015-09-05 18:04:43
【问题描述】:
tl;dr
如果库是由可执行文件或另一个共享库链接的,linux 加载和链接共享库的方式有什么不同吗?
背景
假设我有一个共享库(例如libA.so),其中包含一个带有静态std::map 的类和一组单例类。每个单例类都可以访问地图并将其自身的实例静态添加到地图中。
有两种情况:
- 我在可执行文件中使用共享库 (
libA.so) 从全局映射中读取所有已注册的类。 - 我在另一个共享库 (
libB.so) 中使用共享库 (libA.so),并在可执行文件中使用这个新库。在这种情况下,libB.so使用来自libA.so的映射为可执行文件提供一些功能(如外观)。
问题
如果我在可执行文件中使用(即链接)这个共享库(场景 1),如果我在另一个共享库中使用这个库并且然后在可执行文件中使用新的(场景2),地图似乎是空的。
我似乎无法理解链接器在这两种情况下如何处理共享库。
更新
事实证明,libB.so 没有正确链接到 libA.so,即使使用 g++ 的 -lA 标志明确指示也是如此。即使我看不到libB.so 使用ldd、pmap 或objdump 链接的libA.so,但在使用libA.so 的类时我没有遇到运行时错误。如果我使用 clang++ 运行相同的命令,我可以看到列出了 所有 所需的库。
【问题讨论】:
-
在 UNIX 系统上,共享库仅为其代码页共享内存。除非您编写特殊代码使库使用共享内存,否则数据页仍与使用库的进程一起驻留。我相信 Windows 有一种 DLL 将共享数据和代码的模式。
-
@jxh 我在 Linux 上,但仍然无法理解当我通过另一个共享库链接共享库时所有这些静态初始化会发生什么,以及为什么如果通过可执行文件直接链接它就可以正常工作?
-
当您生成第二个库时,您是否 100% 确定您对第一个共享库进行了静态链接?
-
@jxh 我更新了这个问题,希望现在更清楚了。
-
@eugeniu-rosca 我 100% 确定我不会静态链接它,因为我的库应该被其他模块使用。
标签: c++ linux linker g++ clang++