【问题标题】:g++ doesn't resolve pthread_once used in stdlibc++g++ 无法解析 stdlibc++ 中使用的 pthread_once
【发布时间】:2016-09-26 07:43:21
【问题描述】:

我是用gtest、stdlibc++和pthread静态链接一个程序,链接命令如下

g++ -static -L/usr/local/lib -o test run_test.o -lgtest -lstdc++ -lgcc -lgcc_eh -lpthread -lc

它可以生成二进制文件,但每次我跟踪核心转储时都会崩溃

#0 0x0000000000000000 在 ?? () #1 0x000000000048bf11 在 __gthread_once (__func=0x48beb0 , __一次=) 在/home/abuild/rpmbuild/BUILD/gcc-4.8.5/obj-x86_64-suse-linux/x86_64-suse-linux/libstdc++-v3/include/x86_64-suse-linux/bits/gthr-default.h: 699 #2 std::locale::_S_initialize () at ../../../../../libstdc++-v3/src/c++98/locale_init.cc:276 #3 0x000000000048bf53 在 std::locale::locale (this=0x7e3a98 ) 在../../../../../libstdc++-v3/src/c++98/locale_init.cc:210 #4 0x000000000045798c 在 basic_streambuf (this=) 在 /home/abuild/rpmbuild/BUILD/gcc-4.8.5/obj-x86_64-suse-linux/x86_64-suse-linux/libstdc++-v3/include/streambuf:466 #5 stdio_sync_filebuf (__f=0x7dd580 , this=) 在/home/abuild/rpmbuild/BUILD/gcc-4.8.5/obj-x86_64-suse-linux/x86_64-suse-linux/libstdc++-v3/include/ext/stdio_sync_filebuf.h:77 #6 std::ios_base::Init::Init (this=) at ../../../../../libstdc++-v3/src/c++98/ios_init.cc:85 #7 0x00000000004028fe 在 __static_initialization_and_destruction_0 (__initialize_p=1, __priority=65535) 在 /usr/include/c++/4.8/iostream:74 #8 0x0000000000402927 in _GLOBAL__sub_I_main () at run_test.cpp:7 #9 0x00000000004ac017 in __libc_csu_init (argc=argc@entry=1, argv=argv@entry=0x7ffcdf8db6d8, envp=0x7ffcdf8db6e8) 在 elf-init.c:88 #10 0x00000000004ababd in __libc_start_main (main=0x4028ae, argc=1, argv=0x7ffcdf8db6d8, 初始化=0x4abfa0,fini=0x4ac030,rtld_fini=0x0,stack_end=0x7ffcdf8db6c8) 在 libc-start.c:244 #11 0x00000000004027c7 in _start () at ../sysdeps/x86_64/start.S:122

并反汇编在std::locale::_S_initialize()中找到的二进制,生成二进制callq 0,而不是调用pthread_once的地址。

48bf0c:e8 ef 40 b7 ff callq 0

使用objdump转储符号表,发现

0000000000000000 w *UND* 0000000000000000 pthread_once 0000000000000000 w *UND* 0000000000000000 __pthread_once

这表明链接器知道 pthread_once 是未定义的弱符号并拒绝解析它。我必须添加链接器选项 -Wl,--undefined=pthread_once 以强制链接器解析 pthread_once 以避免崩溃。

有人知道为什么链接器不能解析 pthread_once 吗?

【问题讨论】:

标签: c++ gcc linker


【解决方案1】:

检查 -Wl,--whole-archive -lpthread -Wl,--no-whole-archive as n.m.提到,它有效。更相关的参考可以在https://gcc.gnu.org/ml/gcc/2014-11/msg00246.html

崩溃来自于 libstdc++ 如何使用weakref 属性在pthread 之上实现一个名为gthread 的包装器。总之,发生崩溃是因为

  1. libstdc++ 假定如果定义了 __pthread_key_create,则定义了 pthread_once,而静态链接则不是这样。
  2. pthread_once 未在用户代码的任何其他位置引用或定义。
  3. gnu 链接器无法解析未定义的弱符号 pthread_once,没有链接错误且 pthread_once 的地址设置为 0。
  4. pthread_once 被调用。

我同意 --whole-archive 链接选项对于 stdlibc++ 和 pthread 的静态链接可能是最简单的解决方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-09-26
    • 1970-01-01
    • 1970-01-01
    • 2019-01-24
    • 2011-02-19
    • 2023-04-03
    • 2012-07-12
    • 1970-01-01
    相关资源
    最近更新 更多