简体   繁体   中英

Why does linking with pthread cause a segmentation fault?

I have a stripped down simple program with a static variable ('abc.cpp'):

#include <iostream>

int main(int, char**)
{
  static const std::string a("123");
  std::cout << "Hello world" << std::endl;
  return 0;
}

I compile it and it works:

> g++ -ggdb abc.cpp -o abc
> ./abc
Hello world

However, if I link in the pthread library....

> g++ -ggdb -lpthread abc.cpp -o abc
> ./abc
Segmentation fault (core dumped)

> gdb abc
(gdb) run
Starting program: abc

Program received signal SIGSEGV, Segmentation fault.
0x0000000000000000 in ?? ()
(gdb) where
#0  0x0000000000000000 in ?? ()
#1  0x00007ffff7b01681 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#2  0x00007ffff7b016c3 in std::locale::locale() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3  0x00007ffff7afe244 in std::ios_base::Init::Init() ()
   from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4  0x0000000000400d03 in __static_initialization_and_destruction_0 (__initialize_p=1,
    __priority=65535) at /usr/include/c++/4.9/iostream:74
#5  0x0000000000400d2c in _GLOBAL__sub_I_main () at abc.cpp:8
#6  0x0000000000400d7d in __libc_csu_init ()
#7  0x00007ffff74a6e55 in __libc_start_main (main=0x400c06 <main(int, char**)>, argc=1,
    argv=0x7fffffffdb58, init=0x400d30 <__libc_csu_init>, fini=<optimised out>,
    rtld_fini=<optimised out>, stack_end=0x7fffffffdb48) at libc-start.c:246
#8  0x0000000000400b39 in _start ()

I know it doesn't use threading here, but in the actual non-stripped-down program, it links to a library that does use threading. It feels like it should be okay to link to pthread even though threading is not actually used.

Interestingly, adding the sanitizer makes it not crash (not sure if that's an "undefined"/unstable fix for it or not...).

> g++ -ggdb -fsanitize=undefined -lpthread abc.cpp -o abc
> ./abc
Hello world

Why does this cause a segfault?

Side note: Clang works.

> clang++ -ggdb -lpthread abc.cpp -o abc
> ./abc
Hello world

Version info:

> g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.9/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.9.2-0ubuntu1~14.04' --with-bugurl=file:///usr/share/doc/gcc-4.9/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.9 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.9 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.9-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.9-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.9-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.9.2 (Ubuntu 4.9.2-0ubuntu1~14.04)

> dpkg -l 'libstdc++6*'
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name                Version        Architecture   Description
+++-===================-==============-==============-===========================================
ii  libstdc++6:amd64    5-20150329-1ub amd64          GNU Standard C++ Library v3
un  libstdc++6-4.0-dbg  <none>         <none>         (no description available)
un  libstdc++6-4.1-dbg  <none>         <none>         (no description available)
un  libstdc++6-4.2-dbg  <none>         <none>         (no description available)
un  libstdc++6-4.3-dbg  <none>         <none>         (no description available)
un  libstdc++6-4.4-dbg  <none>         <none>         (no description available)
un  libstdc++6-4.5-dbg  <none>         <none>         (no description available)
un  libstdc++6-4.6-dbg  <none>         <none>         (no description available)
un  libstdc++6-4.7-dbg  <none>         <none>         (no description available)
un  libstdc++6-4.8-dbg  <none>         <none>         (no description available)
ii  libstdc++6-4.9-dbg: 4.9.2-0ubuntu1 amd64          GNU Standard C++ Library v3 (debugging file
un  libstdc++6-5-dbg    <none>         <none>         (no description available)
un  libstdc++6-dbg      <none>         <none>         (no description available)

Here's the ldd abc for gcc build:

linux-vdso.so.1 => (0x00007ffef8f2f000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f87b167c000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f87b1465000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f87b109f000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f87b0d99000)
/lib64/ld-linux-x86-64.so.2 (0x00007f87b1a11000)

And the ldd abc for clang build (note the pthread here and not in gcc):

linux-vdso.so.1 => (0x00007fffa4cc7000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fab1f10d000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fab1ed94000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fab1ea8d000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fab1e876000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fab1e4b1000)
/lib64/ld-linux-x86-64.so.2 (0x00007fab1f347000)

For what it's worth, my locale:

> locale
LANG=en_AU.UTF-8
LANGUAGE=en_AU:en
LC_CTYPE="en_AU.UTF-8"
LC_NUMERIC="en_AU.UTF-8"
LC_TIME="en_AU.UTF-8"
LC_COLLATE="en_AU.UTF-8"
LC_MONETARY="en_AU.UTF-8"
LC_MESSAGES="en_AU.UTF-8"
LC_PAPER="en_AU.UTF-8"
LC_NAME="en_AU.UTF-8"
LC_ADDRESS="en_AU.UTF-8"
LC_TELEPHONE="en_AU.UTF-8"
LC_MEASUREMENT="en_AU.UTF-8"
LC_IDENTIFICATION="en_AU.UTF-8"
LC_ALL=

Setting the default locale results in the same (and the same stack trace too):

> LC_ALL=C ./abc
Segmentation fault (core dumped)

The issue is actually a bug in the gold linker your system is probably using by default. Check the name printed by ld --version. The bug appears to still be open: https://sourceware.org/bugzilla/show_bug.cgi?id=16417

Using the standard bfd linker does not show this problem. The linker used is either defined by gcc -fuse-ld=gold or the symlink in /usr/bin/ld

The libstdc++6 package you have installed is not even in Ubuntu!

ii  libstdc++6:amd64  5-20150329-1ubuntu11 amd64    GNU Standard C++ Library v3

From packages.ubuntu.com :

trusty (14.04LTS) (libs): GNU Standard C++ Library v3
    4.8.2-19ubuntu1: amd64 i386
utopic (libs): GNU Standard C++ Library v3
    4.9.1-16ubuntu6: amd64 i386
vivid (libs): GNU Standard C++ Library v3
    4.9.2-10ubuntu13: amd64 i386 

I would recommend checking your /etc/apt/sources.list and removing the line that caused installation of the package. I think it may be ppa:ubuntu-toolchain-r/test , a PPA for " Toolchain test builds "...

Then you can try to downgrade your libstdc++6 package to get back to a sane version (appropriate for the Ubuntu version you have installed). While you are at it, you should carefully check if other packages are affected as well. You don't want to run your system on test-builds of your core libraries.

By the way, that also explains why gdb did not find the debug symbols, they were for another version of the library.

It turns out it was the GCC compiler or libstdc++ that is buggy/broken. Linking with pthread shouldn't cause a segfault.

Clang didn't segfault, which is using the same libstdc++, so that suggests it may be the compiler. I tested with gcc version 5.1.0 (Ubuntu 5.1.0-0ubuntu11~14.04.1) and found it worked, so it confirms the GCC/libstdc++ bug.

The original GCC 4.9 which was used was from an unofficial test compiler repository ( https://launchpad.net/~ubuntu-toolchain-r/+archive/ubuntu/test ) - not the official Ubuntu repository. However the GCC 5.1 that was tested, was also from the same repository, so at least the bug was fixed there. It is not known as to whether the official Ubuntu GCC 4.8 causes this segfault or not.

$ man gcc

is your friend. There is more to using the threading library than just including the library in the linking step: the files should be compiled using the "-pthread" switch too.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM