tl; dr
如果库是通过可执行文件或其他共享库链接的,则linux加载和链接共享库的方式是否有所不同?
背景
假设我有一个共享库(例如libA.so
),其中包含一个带有静态类的类std::map
和一组单例类。每个单例类都可以访问地图,并将自身的实例静态添加到地图。
有两种情况:
libA.so
在可执行文件中使用共享库()从全局映射中读取所有已注册的类。libA.so
在另一个共享库(libB.so
)中使用了共享库(),并在可执行文件中使用了这个新库。在这种情况下,libB.so
使用map fromlibA.so
为可执行文件(如外观)提供某些功能。问题
如果我在可执行文件中使用(即链接)此共享库(场景1),则上述映射包含单例类的列表,但是,如果我在另一个共享库中使用此库,然后在可执行文件中使用新的共享库(场景1) 2),地图似乎是空的。
在这两种情况下,我似乎都无法理解链接器如何处理共享库。
更新
事实证明libB.so
,libA.so
即使使用-lA
标志明确指示也无法正确链接g++
。虽然我不能看到libA.so
通过连接libB.so
使用ldd
,pmap
或者objdump
,我使用的类时,没有得到运行时错误libA.so
。如果我运行相同的命令,则clang++
可以看到所有必需的库均已列出。
我将描述一种可能产生您所看到的行为的方案。
另一种情况:
libB.so
从全局构造函数中读取地图,则可能在任何对象有机会将其注册之前调用该地图。通常,不能保证从不同的翻译单元(当然也不能从不同的共享库)执行全局构造函数的顺序。
上面第一个问题的解决方案是为地图使用单例样式模式,以便在使用时对其进行初始化,而不是通过全局构造函数进行初始化。
TheMap & GlobalMap () {
static TheMap instance;
return instance;
}
上面第二个问题的解决方案是禁止从全局构造函数访问全局地图。也就是说,将所有全局构造函数更改libB.so
为在使用时进行初始化,而不是在全局构造函数中进行初始化。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句