将静态库链接到 exe 和共享库后出现段错误

segfault after linking static library into both exe and shared lib

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

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

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

So it seems like there are two copies of the global static variable?

是的,这是预期的。

Shouldn't the executable override the symbol from shared library so there is only one global static variable in the executable during dynamic linking?

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

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

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

there is another executable that does the same as above, which seems to behave okay

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