4

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)
Jetski S-type
  • 1,138
  • 2
  • 16
  • 32
  • 1
    All signs point to a bug in GCC until proven otherwise. – Jeff Hammond Apr 22 '15 at 02:37
  • Can you tell us what the library you're actually linking with is? –  Apr 22 '15 at 02:39
  • @Jeff: Oh! Confirmation would be nice. Also confirmation that it's fixed in 5.0 would be nice. – Jetski S-type Apr 22 '15 at 05:28
  • @duskwuff: I made it myself, and it's hardly relevant here. – Jetski S-type Apr 22 '15 at 05:28
  • And by 5.0, I mean 5.1. – Jetski S-type Apr 22 '15 at 05:40
  • @JetskiS-type The behavior you're describing sounds sufficiently bizarre that I suspect there's something odd about your library, or the way you've built it, that's causing this. –  Apr 22 '15 at 05:51
  • 1
    Since it looks like a null pointer crash in `libstdc++`, can also install the [debug package](http://packages.ubuntu.com/search?suite=all&section=all&arch=i386&keywords=libstdc%2B%2B+dbg&searchon=names) Then the stack trace should be more informative. This only adds external debug info files, so it doesn't alter your `libstdc++` library files. – Christian Aichinger Apr 22 '15 at 06:16
  • @duskwuff: The non-stripped-down version uses the other library. The stripped-down version here that doesn't use the library is sufficient to get it to have weird behaviour. Thus, the library is irrelevant. – Jetski S-type Apr 22 '15 at 06:21
  • @ChristianAichinger: I installed package libstdc++6-4.9-dbg. However it has the stack trace as before: "#1 0x00007ffff7b01681 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6" Not sure if this is the new debug library I just installed or not... I did try "-D_GLIBCXX_DEBUG" (http://stackoverflow.com/questions/16023934/debug-through-libstdc), but it still didn't work. – Jetski S-type Apr 22 '15 at 06:39
  • You got the correct -dbg package, right (no multiarch i386 variant or so)? GDB should automatically find the debug info (though debuglink), but you can also [specify the path to the debug info](https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html] manually. – Christian Aichinger Apr 22 '15 at 07:10
  • Since stack trace involves initialization of locale, what locale are you using? Please provide output of `locale`, and try to run it with `POSIX C` locale: `LC_ALL=C ./abc` – myaut Apr 22 '15 at 08:01
  • I cannot reproduce this on Mac x86_64 with `Homebrew gcc 4.9.2_1 --without-multilib`, but the C++ standard library situation on my machine is likely different than on Linux. In any case, I don't see any evidence that it's a bug in GCC code generation. – Jeff Hammond Apr 22 '15 at 14:21
  • What is the exact version of `libstdc++6`? (Run `dpkg -l 'libstdc++6*'` to find out.) Please **edit** your question to include that. Could you please also include the locale and `ldd` data in the question and delete your comments? The comment section is pretty hard to read. – Christian Aichinger Apr 23 '15 at 15:57
  • @ChristianAichinger: Done. Is it usual to put the extra info on the way to solving it as requested by others, which may or may not be slightly tangential, as an edit to the question? It is a bit frustrating that all new lines are removed from the comments... – Jetski S-type Apr 24 '15 at 08:53
  • In my case there was a segfault because of static linking with pthread - https://stackoverflow.com/questions/35116327/when-g-static-link-pthread-cause-segmentation-fault-why – Vadim Kotov Aug 11 '18 at 12:08

4 Answers4

3

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

jtaylor
  • 2,389
  • 19
  • 19
  • It's not using gold by default - I made it use gold when using the /usr/bin/ld symlink. I need gold for LTO in Clang. Thanks, it looks similar, but I'm not completely sure... is it just a combination of compiler/linker that causes it, and not other combinations with a different compiler? Remember, while still using the same gold linker, Clang and GCC 5.1 both worked fine.... I also (don't think?) mine is using the -Wl,--as-needed flag, like they seemed to required in their bug. – Jetski S-type Aug 21 '15 at 01:29
  • When the ld symlink points to gold that is used by default. --as-needed is used by default in the standard ubuntu linker, its hardcoded in the gcc specs ubuntu ships. Though it is possible there is some interaction, I haven't tested 5.1 with that configuration. – jtaylor Aug 21 '15 at 17:31
2

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.

Christian Aichinger
  • 6,989
  • 4
  • 40
  • 60
  • Correct! I did get my GCC build from https://launchpad.net/~ubuntu-toolchain-r/+archive/ubuntu/test. The one included in Ubuntu 14.04 LTS (4.8) is too old for my liking. Pages such as [this](http://ubuntuhandbook.org/index.php/2013/08/install-gcc-4-8-via-ppa-in-ubuntu-12-04-13-04/) (old, but same principle applies) and [this](http://askubuntu.com/questions/466651/how-do-i-use-the-latest-gcc-4-9-on-ubuntu-14-04) seem to suggest it's an okay thing to do. I assume it's close enough to the actual 4.9.2 release. I prefer 4.9 or 5.1, so I may even try 5.1 at some point... – Jetski S-type Apr 28 '15 at 00:44
  • You can use [gcc 4.9](http://packages.ubuntu.com/utopic/gcc) from utopic. ``ubuntu-toolchain-r`` is even more cutting edge than vivid, it's an unsupported test package. Personally, I would not develop on it, because you'll never know if a crash is your fault or the toolchains's. The gcc 5 features aren't worth running into problems like this one. – Christian Aichinger Apr 28 '15 at 04:44
  • Utopic (14.10) is not an LTS, and I need to use an LTS version. Ah, the tension between solid support and cutting edge. GCC 4.9 and 5.1 are big steps forward from 4.8, so I'm not willing to step backwards. GCC 4.9 was released a year ago, so it's a shame that it's still not fixed in the cutting edge "test" version. It would make sense for it to be very close to the official 4.9.2 release. – Jetski S-type Apr 28 '15 at 05:38
  • Confirmed: GCC 5.1 (from ubuntu-toolchain-r/test: `gcc version 5.1.0 (Ubuntu 5.1.0-0ubuntu11~14.04.1)`) does fix this seg fault. That's good. So that version of libstdc++ is to blame then. – Jetski S-type Apr 28 '15 at 05:56
  • I'm marking this as the solution, even though I don't like the tone of it. Could you please improve it by stating that the seg fault is caused by a bug in libstdc++, which is an unofficial unsupported version? You could reference my GCC 5.1 test as proof of this bug that was fixed. You can then put steps of how to go back to the official GCC package after that. – Jetski S-type Apr 28 '15 at 06:03
  • Sorry mate, the rejectors of my edit suggestion seemed to imply that the best course of action was to make my own answer... Upvote for suggesting to try a different compiler version and the reason why gdb wasn't showing symbols. – Jetski S-type Apr 30 '15 at 09:03
2

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.

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Jetski S-type
  • 1,138
  • 2
  • 16
  • 32
-4
$ 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.

  • GCC documentation is your friend too: https://gcc.gnu.org/onlinedocs/gcc-4.9.2/gcc/Option-Summary.html#Option-Summary Searching for '-pthread' option reveals it in sections 'RS/6000 and PowerPC Options', and 'Solaris 2 Options'. I'm using x86_64, so I feel like this option is irrelevant for my platform. Is this not correct? – Jetski S-type Apr 22 '15 at 06:23
  • My compiling and linking is done in the one command. I did try this, and replacing '-lpthread' with '-pthread' resulted in exactly the same segmentation fault. – Jetski S-type Apr 22 '15 at 06:28
  • At least with C11, that flag shouldn't be necessary anymore. And GCC has been following C11 memory model for a decade or so, as far as I know. – Jeff Hammond Apr 22 '15 at 14:14
  • 1
    And, as I suspected, the `-pthread` compilation option has absolutely no impact whatsoever on the GCC 4.9.2 code generation on Mac x86_64, as measured using the assembly output. – Jeff Hammond Apr 22 '15 at 14:18