【问题标题】:Shared library libbar.so static linking to libfoo.a, program linking to libbar.so and libfoo.so, what happens?共享库 libbar.so 静态链接到 libfoo.a,程序链接到 libbar.so 和 libfoo.so,会发生什么?
【发布时间】:2015-12-15 00:36:41
【问题描述】:

(希望这不会变得太复杂......)

我已经构建了一个第三方 C++ 库 libfoo,其中包含静态 (libfoo.a) 和共享 (libfoo.so) 版本。目标文件是使用 -fPIC 创建的。 libfoo 有几个用于配置其行为的全局变量,以及依赖这些全局变量的函数,为简单起见,函数 func1() 与变量 global_a 交互。

我已经构建了我的 C++ 共享库 libbar,我已经静态链接到 libfoo.a。这是在没有 --whole-archive 选项的情况下完成的。所以我相信libbar.so 包含了libfoo.a 所需的所有符号和定义。这个库调用来自libfoo 的函数,它使用全局变量来控制行为。在这种情况下,假设它调用函数func1()

最后,我有一个 C++ 客户端程序 baz,它动态链接到 libfoo.solibbar.so。此客户端还使用来自libfoo 的相同函数/全局变量。它修改global_a并调用func1()

一般来说,在这种情况下客户端baz 的行为是什么?这种配置是我应该避免的,还是可以?如果libfoo.alibfoo.so 是不同的版本会怎样?

对于全局变量,我有点期待libbar.so 中的代码会使用自己的副本,baz 中的任何更改都会修改libfoo.so 中的副本,但这不是我所看到的。当baz修改global_a时,在libbar.so中可以看到效果。客户端baz 没有我能看出的任何其他异常行为。

我还尝试将bazlibfoo.a 链接,并看到相同的(显然是正确的)行为。

无论哪种情况,Valgrind 都没有显示任何错误。

【问题讨论】:

    标签: c++ linker global-variables shared-libraries static-libraries


    【解决方案1】:

    一般来说,在这种情况下,客户端 baz 的行为会是什么?

    一般而言,UNIX / ELF 系统上共享库的行为旨在模仿存档库的行为。

    特别是,如果您的二进制文件 baz 链接到 libfoo.solibbar.so,两者export global_a,那么第一个定义获胜。也就是说,从bazlibfoo.solibbar.soglobal_a 的所有引用都将绑定到在链接顺序中找到的第一个实例(这里大概是libfoo.so)。

    可以通过隐藏符号来修改此行为,例如-fvisibility-hidden__attribute__((visibility("hidden"))) 或链接器脚本。

    您可以通过

    查看每个库导出的内容
    nm -AD libfoo.so libbar.so | grep global_a
    

    (此命令将只显示导出的符号)。

    对于全局变量,我有点期待 libbar.so 中的代码会使用自己的副本

    这种预期是不正确的。

    这种配置是我应该避免的,还是可以的?

    这是您通常应该避免的事情,因为例如更新libbar.so 而不重新链接libfoo.so 可能会产生不一致。假设global_a 的类型在以后的版本中从int 更改为double。突然一个简单的语句,如:

    global_a = 0.0;
    

    libbar.so 内部现在可能会损坏libfoo.so 内部global_a 之后的不相关变量(libfoo.so 内部的global_a 仍然是一个 4 字节 int,但现在写入了 8 字节 double进去)。

    无论哪种情况,Valgrind 都没有显示错误。

    Valgrind 在检查全局变量方面异常很弱,而且几乎从不抱怨它们。您应该养成使用gcc -fsanitize=address 检查程序的习惯。

    【讨论】:

    • 谢谢,这很有帮助。你有什么参考资料可以让我读到这样的东西吗?至于-fsanitize,不幸的是我被困在 gcc 4.4.7 (Centos 6) 上,所以我无法使用。
    猜你喜欢
    • 1970-01-01
    • 2018-04-09
    • 1970-01-01
    • 1970-01-01
    • 2015-10-08
    • 1970-01-01
    • 2011-01-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多