【问题标题】:segfault after linking static library into both exe and shared lib将静态库链接到 exe 和共享库后的段错误
【发布时间】:2021-06-11 00:45:56
【问题描述】:

我有一个静态链接 glib 库并动态链接 共享库 的程序,该共享库反过来也静态链接相同的 glib 库。当我运行程序时,我得到一个段错误。在gdb 中调试后,我发现glib 中定义了一个global static 变量,该变量正在设置中,并且它在一个调用跟踪和以后的调用跟踪中具有不同的值。然后我注意到变量地址也不同。所以看起来global static 变量有两个副本?可执行文件不应该覆盖共享库中的符号,以便在动态链接期间可执行文件中只有一个全局静态变量吗?

故事的另一部分是另一个可执行文件与上述相同,它的行为似乎正常,即没有段错误(尚未调试以查看不同的代码路径是否加载相同的静态变量)。所以也许这种行为不是确定性的。 Linux 上的gcc (8.3.1) (centos 7) 出现以下问题。

executableA (segfault)                          executableB (no segfault)
|            \                                     |        \
| (static)    \(shared)                            |(static) \(shared)
|              \                                   |          \
libglib-2.0.a   libA.so                        libglib-2.0.a   libA.so
                 |                                               |
                 | (static)                                      |(static)
                 |                                               |
              libglib-2.0.a                                  libglib-2.0.a

【问题讨论】:

  • 请注意,共享库是我从源代码构建的第三方库。

标签: gcc linker static-linking dynamic-linking


【解决方案1】:

所以看起来全局静态变量有两个副本?

是的,这是意料之中的。

难道可执行文件不应该覆盖共享库中的符号,因此在动态链接期间可执行文件中只有一个全局静态变量吗?

static 变量根据定义具有本地链接——它不能从任何其他编译单元访问,也不能从共享库中导出。

您必须使这个变量(以及任何其他类似变量)静态并从两个共享库中导出。只有这样,动态加载器才会将此变量的所有引用绑定到单个实例。

请注意,将libglib-2.0.a 的单独副本链接到共享库 不控制符号可见性是自问 麻烦。无论您希望通过这样做来实现什么,您都没有实现了。

还有另一个可执行文件与上面的功能相同,它似乎表现不错

啊,programming by coincidence。你踩到的地雷没有爆炸,继续做应该没问题。

【讨论】:

  • 你能解释一下“控制符号可见性”是什么意思吗? glib 库静态链接到我从源代码构建的第三方库。
  • 无论如何,因为我知道 glib 已经静态链接到第三方共享库中,所以我不需要在我的可执行文件中再次链接它。但是,如果我在加载共享库之前不知道或需要使用 glib 怎么办?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-08
  • 1970-01-01
  • 2011-03-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多