【问题标题】:Why does this linker warning and segment fault happen?为什么会发生此链接器警告和段错误?
【发布时间】:2021-10-23 04:14:20
【问题描述】:

我最近将一些外部库版本从 librdkafka 1.3.0 升级到了 librdkafka 1.6.1。

构建外部库后,它被链接为共享对象。

然后我的程序链接时出现以下警告。

/opt/rh/devtoolset-7/root/usr/libexec/gcc/x86_64-redhat-linux/7/ld:
Warning: type of symbol `mtx_lock' changed from 2 to 1 
in ../externals/synapfilter/lib/libsnf.a(memoryUtil.cpp.o)

在程序执行期间也发生了段错误。 gdb的输出如下。

Program terminated with signal SIGSEGV, Segmentation fault.
b#0  0x0000000000f27a80 in mtx_lock ()
Missing separate debuginfos, use: debuginfo-install bzip2-libs-1.0.5-7.el6_0.x86_64 cyrus-sasl-lib-2.1.23-15.el6_6.2.x86_64 glibc-2.12-1.192.el6.x86_64 keyutils-libs-1.4-5.el6.x86_64 krb5-libs-1.10.3-57.el6.x86_64 libcom_err-1.41.12-22.el6.x86_64 libgcc-4.4.7-17.el6.x86_64 libicu-4.2.1-14.el6.x86_64 libselinux-2.0.94-7.el6.x86_64 libstdc++-4.4.7-17.el6.x86_64 libzstd-1.4.5-3.el6.x86_64 lz4-r131-1.el6.x86_64 nss-softokn-freebl-3.14.3-23.3.el6_8.x86_64 openssl-1.0.1e-57.el6.x86_64 zlib-1.2.3-29.el6.x86_64
(gdb) bt
#0  0x0000000000f27a80 in mtx_lock ()
#1  0x00007f59479a38cc in rd_kafka_global_cnt_incr () at rdkafka.c:182
#2  rd_kafka_new (type=type@entry=RD_KAFKA_PRODUCER, app_conf=app_conf@entry=0x2531870, errstr=errstr@entry=0x7ffd71c7c7d0 <incomplete sequence \350>,
    errstr_size=errstr_size@entry=512) at rdkafka.c:2092

发现使用的两个外部库中的name(mtx_lock)重复了。

它被用作libsnf.a的一个目标文件中的全局变量。

$ objdump -t memoryUtil.cpp.o | grep mtx_lock
0000000000000000 g     O .bss   0000000000000028 mtx_lock

该名称还被用作 librdkafka.a 的一个目标文件中的函数。

$ objdump -t tinycthread.o | grep mtx_lock
0000000000000090 g     F .text  0000000000000016 mtx_lock

我想知道为什么会发生这种情况以及如何解决它。

在我的 makefile 中,我将 libsnf.a 链接为静态库,将 librdkafka.so 链接为动态库。

【问题讨论】:

  • 这称为名称冲突。
  • 一个名为 libfoo 的负责任的库只会导出名称以 foo 开头的符号,因此应该是 snfmtx_lock。导出通用名称是自找麻烦。
  • 向两个库提交错误报告,希望其中一个或两个都修复它
  • 好的,那么除了报告bug,在使用./configure命令创建共享库时,有什么办法可以修复它?

标签: c++ c linux linker g++


【解决方案1】:

不知道为什么会这样

您有两个单独的目标文件:memoryUtil.cpp.otinycthread.o,定义相同的符号:mtx_lock。其中一个将其定义为函数,另一个将其定义为变量。

通常这会导致链接时出现“多重定义”符号错误,但您会收到警告。我不知道为什么;也许其中一个符号定义很弱。

(一般来说,你不应该使用objdump 来查看ELF 符号——改用readelf -Ws。)

您的程序继续调用 mtx_lock(),但取而代之的是一个数据变量,然后崩溃了。

以及如何解决它。

由于这些库是开源的,最简单的解决方法是重命名一个(或两个)变量,然后重新构建。

如果你不想重建,你可以使用objcopy --redefine-sym ... 来达到同样的效果。

更新:

mtx_lock() 函数是C11 standard 的一部分,这使得将其用作libsnf 中的变量存在很大问题。

【讨论】:

  • mtx_lock() 是由 C11 定义的,因此强烈建议更改变量名而不是函数(tinycthread 的 mtx_lock() 函数是用于 C11 线程不可用的系统的 pthread-wrapper) .
猜你喜欢
  • 1970-01-01
  • 2011-11-10
  • 2015-09-29
  • 1970-01-01
  • 1970-01-01
  • 2012-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多