C++ 共享库libbar.so静态链接到libfoo.a,程序链接到libbar.so和libfoo.so,会发生什么?
(希望这不会变得太复杂…)C++ 共享库libbar.so静态链接到libfoo.a,程序链接到libbar.so和libfoo.so,会发生什么?,c++,linker,global-variables,shared-libraries,static-libraries,C++,Linker,Global Variables,Shared Libraries,Static Libraries,(希望这不会变得太复杂…) 我已经构建了一个第三方C++库 LBFoO ,同时使用静态()和共享( LBoFo.S.)版本。对象文件是使用-fPIC创建的libfoo有几个用于配置其行为的全局变量,以及依赖这些全局变量的函数,为了简单起见,函数func1()与变量global\u a交互 我已经构建了我的C++共享库 LabBar ,我静态链接到 LBFoO。这是在没有--whole archive选项的情况下完成的。所以我相信libbar.So包含了它需要的libfoo.a中的所有符号和定义。
我已经构建了一个第三方C++库<代码> LBFoO ,同时使用静态(
有几个用于配置其行为的全局变量,以及依赖这些全局变量的函数,为了简单起见,函数libfoo
与变量func1()
交互global\u a
libbar.So
包含了它需要的libfoo.a
中的所有符号和定义。此库从libfoo
调用函数,该函数使用全局变量控制行为。在本例中,假设它调用函数func1()
<>最后,我有一个C++客户端程序<代码> BAZ./COD>动态链接到<代码> libfo。所以和libfoo
的相同函数/全局变量。它修改global\u a
并调用func1()
一般来说,在这种情况下,客户baz
的行为是什么?这种配置是我应该避免的,还是可以?如果libfoo.a
和libfoo.so
是不同的版本,会发生什么
对于全局变量,我有点希望libbar.so
中的代码会使用自己的副本,而baz
中的任何更改都会修改libfoo.so
中的副本,但这不是我看到的。当baz
修改global_a
时,效果可以在libbar.so
中看到。客户baz
没有任何其他异常行为,我看不出来
我还尝试将baz
链接到libfoo.a
,并看到了相同的(显然是正确的)行为
Valgrind在这两种情况下均未显示任何错误
一般来说,在这个场景中,客户端baz的行为是什么
通常,UNIX/ELF系统上共享库的行为旨在模仿归档库的行为
特别是,如果您的二进制baz
链接到libfoo.so
和libbar.so
,两者都导出global\u a
,则第一个定义获胜。也就是说,来自baz
、libfoo.so
和libbar.so
的所有对global_a
的引用都将绑定到链接顺序中找到的第一个实例(这里大概是libfoo.so
)
可以通过隐藏符号来修改此行为,例如使用-fvisibility hidden
、使用\uuuu属性((可见性(“隐藏”))
或使用链接器脚本
您可以使用查看每个库导出的内容
nm -AD libfoo.so libbar.so | grep global_a
(此命令将仅显示导出的符号)
对于全局变量,我希望libbar.so中的代码使用自己的副本
这种期望是不正确的
这种配置是我应该避免的,还是可以
这是您通常应该避免的,因为例如更新libbar.so
而不重新链接libfoo.so
可能会产生不一致性。假设global\u a
的类型在以后的版本中从int
更改为double
。突然间,一个简单的陈述如下:
global_a = 0.0;
内部libbar.so
现在可能会损坏global\u a
内部libfoo.so
(内部libfoo.so
中的global\u a
仍然是一个4字节int
,但现在得到写入其中的8字节double
)
Valgrind在这两种情况下都没有显示错误
Valgrind在检查globals方面异常薄弱,几乎从不抱怨。你应该养成用gcc-fsanize=address检查程序的习惯。谢谢,这非常有用。你有什么参考资料可以让我读到类似的东西吗?至于
-fsanizize
,不幸的是我被GCC4.4.7(Centos 6)卡住了,所以我无法使用它。