g++-8 in disco is broken with libstdc++6 from gcc9 and libstdc++fs

Bug #1824721 reported by Roger Leigh
28
This bug affects 5 people
Affects Status Importance Assigned to Milestone
gcc
Invalid
Medium
gcc-8 (Ubuntu)
Fix Released
Undecided
Unassigned
Bionic
Fix Released
Undecided
Unassigned

Bug Description

There is a significant incompatibility here which leaves the default C++ compiler broken with C++17 std::filesystem usage. Unfortunately, there isn't an obvious workaround since there's only one libstdc++6 package, and it's using the non-default and unreleased GCC9 version of libstdc++, making it impossible to use the compatible GCC8 version of the library.

% cat testpath.cpp
#include <filesystem>

int main()
{
  std::filesystem::path p("test");
}

g++-9 -std=c++17 -lstdc++fs -g3 -o testpath testpath.cpp
% ./testpath

% g++-8 -std=c++17 -lstdc++fs -g3 -o testpath testpath.cpp
% ./testpath
zsh: segmentation fault (core dumped) ./testpath

% gdb testpath
GNU gdb (Ubuntu 8.2.91.20190405-0ubuntu3) 8.2.91.20190405-git
Copyright (C) 2019 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from testpath...
(gdb) run
Starting program: /tmp/testpath

Program received signal SIGSEGV, Segmentation fault.
0x000055555555649b in std::vector<std::filesystem::__cxx11::path::_Cmpt, std::allocator<std::filesystem::__cxx11::path::_Cmpt> >::~vector (this=0x23, __in_chrg=<optimised out>) at /usr/include/c++/8/bits/stl_vector.h:567
567 std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
(gdb) bt
#0 0x000055555555649b in std::vector<std::filesystem::__cxx11::path::_Cmpt, std::allocator<std::filesystem::__cxx11::path::_Cmpt> >::~vector (this=0x23, __in_chrg=<optimised out>) at /usr/include/c++/8/bits/stl_vector.h:567
#1 0x0000555555556314 in std::filesystem::__cxx11::path::~path (this=0x3, __in_chrg=<optimised out>)
    at /usr/include/c++/8/bits/fs_path.h:208
#2 0x0000555555556f5c in std::filesystem::__cxx11::path::_Cmpt::~_Cmpt (this=0x3, __in_chrg=<optimised out>)
    at /usr/include/c++/8/bits/fs_path.h:643
#3 0x0000555555556f77 in std::_Destroy<std::filesystem::__cxx11::path::_Cmpt> (__pointer=0x3)
    at /usr/include/c++/8/bits/stl_construct.h:98
#4 0x0000555555556e27 in std::_Destroy_aux<false>::__destroy<std::filesystem::__cxx11::path::_Cmpt*> (
    __first=0x3, __last=0x0) at /usr/include/c++/8/bits/stl_construct.h:108
#5 0x0000555555556a98 in std::_Destroy<std::filesystem::__cxx11::path::_Cmpt*> (__first=0x3, __last=0x0)
    at /usr/include/c++/8/bits/stl_construct.h:137
#6 0x00005555555567a9 in std::_Destroy<std::filesystem::__cxx11::path::_Cmpt*, std::filesystem::__cxx11::path::_Cmpt> (__first=0x3, __last=0x0) at /usr/include/c++/8/bits/stl_construct.h:206
#7 0x00005555555564b1 in std::vector<std::filesystem::__cxx11::path::_Cmpt, std::allocator<std::filesystem::__cxx11::path::_Cmpt> >::~vector (this=0x7fffffffe310, __in_chrg=<optimised out>)
    at /usr/include/c++/8/bits/stl_vector.h:567
#8 0x0000555555556314 in std::filesystem::__cxx11::path::~path (this=0x7fffffffe2f0, __in_chrg=<optimised out>)
    at /usr/include/c++/8/bits/fs_path.h:208
#9 0x0000555555556230 in main () at testpath.cpp:5
(gdb) quit
A debugging session is active.

        Inferior 1 [process 2414] will be killed.

Quit anyway? (y or n) y

Revision history for this message
In , Mpreda (mpreda) wrote :

#include <filesystem>

int main() {
  std::filesystem::path p = "foo";
}

g++ -g --std=c++17 path.cpp

./a.out
Segmentation fault (core dumped)

g++ --version
g++ (Ubuntu 8.3.0-6ubuntu1) 8.3.0

uname -a
Linux x2 5.0.6-050006-generic #201904030534 SMP Wed Apr 3 05:36:14 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

Ubuntu 19.04.

Core was generated by `./a.out'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x000055c2ac25149b in std::vector<std::filesystem::__cxx11::path::_Cmpt, std::allocator<std::filesystem::__cxx11::path::_Cmpt> >::~vector (this=0x23, __in_chrg=<optimized out>) at /usr/include/c++/8/bits/stl_vector.h:567
567 std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
(gdb) bt
#0 0x000055c2ac25149b in std::vector<std::filesystem::__cxx11::path::_Cmpt, std::allocator<std::filesystem::__cxx11::path::_Cmpt> >::~vector (this=0x23, __in_chrg=<optimized out>) at /usr/include/c++/8/bits/stl_vector.h:567
#1 0x000055c2ac251314 in std::filesystem::__cxx11::path::~path (this=0x3, __in_chrg=<optimized out>) at /usr/include/c++/8/bits/fs_path.h:208
#2 0x000055c2ac251f5c in std::filesystem::__cxx11::path::_Cmpt::~_Cmpt (this=0x3, __in_chrg=<optimized out>) at /usr/include/c++/8/bits/fs_path.h:643
#3 0x000055c2ac251f77 in std::_Destroy<std::filesystem::__cxx11::path::_Cmpt> (__pointer=0x3) at /usr/include/c++/8/bits/stl_construct.h:98
#4 0x000055c2ac251e27 in std::_Destroy_aux<false>::__destroy<std::filesystem::__cxx11::path::_Cmpt*> (__first=0x3, __last=0x0) at /usr/include/c++/8/bits/stl_construct.h:108
#5 0x000055c2ac251a98 in std::_Destroy<std::filesystem::__cxx11::path::_Cmpt*> (__first=0x3, __last=0x0) at /usr/include/c++/8/bits/stl_construct.h:137
#6 0x000055c2ac2517a9 in std::_Destroy<std::filesystem::__cxx11::path::_Cmpt*, std::filesystem::__cxx11::path::_Cmpt> (__first=0x3, __last=0x0) at /usr/include/c++/8/bits/stl_construct.h:206
#7 0x000055c2ac2514b1 in std::vector<std::filesystem::__cxx11::path::_Cmpt, std::allocator<std::filesystem::__cxx11::path::_Cmpt> >::~vector (this=0x7ffe3ad201d0, __in_chrg=<optimized out>)
    at /usr/include/c++/8/bits/stl_vector.h:567
#8 0x000055c2ac251314 in std::filesystem::__cxx11::path::~path (this=0x7ffe3ad201b0, __in_chrg=<optimized out>) at /usr/include/c++/8/bits/fs_path.h:208
#9 0x000055c2ac251230 in main () at path.cpp:4

Revision history for this message
In , Mpreda (mpreda) wrote :

I would hope somebody would take a look and reject this issues as invalid for some reason, because otherwise it's rather severe.

Revision history for this message
In , Mpreda (mpreda) wrote :

Adding -lstdc++fs fixes the problem with g++ 8.3

g++-9 does not segfault even without -lstdc++fs

g++-9 --version
g++-9 (Ubuntu 9-20190402-1ubuntu1) 9.0.1 20190402 (experimental) [trunk revision 270074]

Revision history for this message
In , Ufospoke (ufospoke) wrote :

I just tried with g++ (GCC) 8.3.1 20190223 (Red Hat 8.3.1-2) on Fedora and it works well. But to be able to link, I had to add -lstdc++fs.

Roger Leigh (rleigh)
affects: gcc-7 (Ubuntu) → gcc-8 (Ubuntu)
Revision history for this message
Roger Leigh (rleigh) wrote :

Note that the strategy for GCC packaging in Ubuntu (maybe also in Debian) is the exact opposite of how RedHat handle GCC packaging for RHEL with the Devtoolset stuff.

Ubuntu is always providing the latest version of libstdc++6 from the newest GCC. This is problematic when the older headers are subtly (or not-so-subtly) incompatible with the shared library.

RedHat always uses the copy of libstdc++ provided by the default compiler for the base system. Newer GCC versions link against this library, with newer functionality provided by static linking of the newer libstdc++ for that GCC version.

Both strategies make compromises. But right now, the default GCC version in Ubuntu is actually broken as a result of the former strategy. Perhaps the default libstdc++6 should be provided by the default GCC version, with later versions adding supplementary functionality via a static library?

Revision history for this message
Matthias Klose (doko) wrote :

No, I think you are bitten by linking with --as-needed as the default., and having the source/object files on the command line before the libraries fixes the issue.

Changed in gcc-8 (Ubuntu):
status: New → Incomplete
Revision history for this message
Matthias Klose (doko) wrote :

Maybe shipping the default libstdc++ with the default compiler is another option, but then you should make -static-libstdc++ the default. Plus how would you provide dynamic linking with the non-default GCC?

Revision history for this message
Roger Leigh (rleigh) wrote :

The link order does seem to be significant as you suggested. However, both the linker and run-time linker succeed without error. The failure is inside the path dtor. While --as-needed may well be at fault, it looks like there may be problems with either not reporting errors, or doing the wrong thing, when the link order isn't right.

Revision history for this message
In , Redi (redi) wrote :

The -lstdc++fs requirement for std::filesystem in GCC 8 is documented in several places:

https://gcc.gnu.org/onlinedocs/gcc-8.3.0/libstdc++/manual/manual/using.html#manual.intro.using.flags
https://gcc.gnu.org/onlinedocs/gcc-8.3.0/libstdc++/manual/manual/status.html#status.iso.2017
https://gcc.gnu.org/onlinedocs/gcc-8.3.0/libstdc++/manual/manual/using_dynamic_or_shared.html#manual.intro.using.linkage.experimental

I don't know why it crashes with Ubuntu, it should be a linker error. I suspect Ubuntu is doing something silly like providing libstdc++.so from GCC 9, which defines std::filesystem::path differently, and so is not compatible with C++17 code compiled using GCC 8.

Revision history for this message
In , Redi (redi) wrote :

Although if you link with -lstdc++fs then it should work OK, because the incompatible std::filesystem symbols in libstdc++.so.6.0.26 won't be used.

Revision history for this message
Matthias Klose (doko) wrote :

there is a link error with:

$ g++-8 -static-libstdc++ -std=c++17 -lstdc++fs -g3 -o testpath testpath.cpp
/usr/bin/ld: /tmp/ccWrH4Ho.o: in function `std::filesystem::__cxx11::path::path<char [5], std::filesystem::__cxx11::path>(char const (&) [5], std::filesystem::__cxx11::path::format)':
/usr/include/c++/8/bits/fs_path.h:184: undefined reference to `std::filesystem::__cxx11::path::_M_split_cmpts()'
collect2: error: ld returned 1 exit status

you won't see it with dynamic linking because in 9, the code from libstdc++fs is now integrated in the libstdc++ library.

Revision history for this message
Jonathan Wakely (jwakely) wrote :

The GCC 8 std::filesystem (and std::experimental::filesystem) symbols are in libstdc++fs.a which is only provided as a static library, so link order does matter. If you don't tell the linker to use it after the objects that require it, then no symbols from libstdc++fs.a will be used.

In GCC 9 the std::experimental::filesystem symbols are still in libstdc++fs.a but the std::filesystem symbols are in libstdc++.so.6.0.26 now, but they're incompatible with the GCC 8 definitions. In your problematic link no symbols were used from libstdc++fs.a, so the linker finds the GCC 9 ones in libstdc++.so.6.0.25 and uses them, but that leads to crashes.

It would have been possible to make the GCC 8 and 9 std::filesystem symbols mangle differently, and maybe I should do that for GCC 8.4, but for now the short answer is "C++17 support in GCC 8 is experimental, the onus is on you to link correctly".

Since this problem is specific to Ubuntu, due to mixing gcc-8 and libstdc++.so.6.0.26, another possibility would be for Ubuntu's gcc-8 to reorder the linker arguments. If -lstdc++fs is given it could be moved to after the object files (but before the implicit -lstdc++ option that g++ adds).

Another option would be to make g++ simply link to -lstdc++fs implicitly, as it does for -lstdc++. Unless the user adds -Wl,--whole-archive (and doesn't follow it with -Wl,--no-whole-archive) that should be harmless because the symbols in libstdc++fs.a will only be used if actually needed.

Revision history for this message
Jonathan Wakely (jwakely) wrote :

Gah, typo:

> so the linker finds the GCC 9 ones in libstdc++.so.6.0.25 and uses them

That should have said libstdc++.so.6.0.26 - sorry for any confusion.

Revision history for this message
In , Mpreda (mpreda) wrote :

OK, thanks.

So if on Ubuntu 19.04, the default compiler produces without errors/warnings, from valid source code, an executable that crashes, that's programmer error?!

I understand the explanation, but there is a problem. Maybe the bug is not with gcc but with Ubuntu, but a bug there is.

Revision history for this message
In , Redi (redi) wrote :

See https://bugs.launchpad.net/ubuntu/+source/gcc-8/+bug/1824721 where I said:

"for now the short answer is "C++17 support in GCC 8 is experimental, the onus is on you to link correctly"

Changed in gcc:
importance: Unknown → Medium
status: Unknown → Invalid
Matthias Klose (doko)
Changed in gcc-8 (Ubuntu):
status: Incomplete → Triaged
Revision history for this message
In , Matthias Klose (doko) wrote :

that's now mitigated by a local patch, always linking with -lstdc++fs.

https://salsa.debian.org/toolchain-team/gcc/blob/gcc-8-debian/debian/patches/pr90050.diff

Revision history for this message
Launchpad Janitor (janitor) wrote :

This bug was fixed in the package gcc-8 - 8.3.0-7ubuntu1

---------------
gcc-8 (8.3.0-7ubuntu1) eoan; urgency=medium

  * Merge with Debian; remaining changes:
    - Build from upstream sources.
    - Don't built common libraries now build from GCC 9.

gcc-8 (8.3.0-7) unstable; urgency=medium

  * Update to SVN 20190428 (r270630) from the gcc-8-branch.
    - Fix PR target/89877 (ARC), PR target/84369 (PPC),
      PR tree-optimization/85762, PR tree-optimization/87008,
      PR tree-optimization/85459, PR target/87532 (PPC),
      PR target/87532 (PPC), PR ipa/89693, PR middle-end/88587,
      PR tree-optimization/90018, PR target/90024 (ARM),
      PR target/89945 (ARM), PR fortran/87352, PR fortran/89981,
      PR fortran/89904, PR libgfortran/79540, PR fortran/87127,
      PR rtl-optimization/87979, PR rtl-optimization/84032.
  * Fix PR c++/90050, always link with libstdc++fs.a. LP: #1824721.
  * Fix PR bootstrap/87338 on ia64 (James Clarke). Closes: #927976.

 -- Matthias Klose <email address hidden> Sun, 28 Apr 2019 09:51:11 +0200

Changed in gcc-8 (Ubuntu):
status: Triaged → Fix Released
Revision history for this message
Łukasz Zemczak (sil2100) wrote : Please test proposed package

Hello Roger, or anyone else affected,

Accepted gcc-8 into bionic-proposed. The package will build now and be available at https://launchpad.net/ubuntu/+source/gcc-8/8.3.0-26ubuntu1~18.04 in a few hours, and then in the -proposed repository.

Please help us by testing this new package. See https://wiki.ubuntu.com/Testing/EnableProposed for documentation on how to enable and use -proposed. Your feedback will aid us getting this update out to other Ubuntu users.

If this package fixes the bug for you, please add a comment to this bug, mentioning the version of the package you tested and change the tag from verification-needed-bionic to verification-done-bionic. If it does not fix the bug for you, please add a comment stating that, and change the tag to verification-failed-bionic. In either case, without details of your testing we will not be able to proceed.

Further information regarding the verification process can be found at https://wiki.ubuntu.com/QATeam/PerformingSRUVerification . Thank you in advance for helping!

N.B. The updated package will be released to -updates after the bug(s) fixed by this package have been verified and the package has been in -proposed for a minimum of 7 days.

Changed in gcc-8 (Ubuntu Bionic):
status: New → Fix Committed
tags: added: verification-needed verification-needed-bionic
Revision history for this message
Launchpad Janitor (janitor) wrote :
Download full text (12.5 KiB)

This bug was fixed in the package gcc-8 - 8.3.0-26ubuntu1~18.04

---------------
gcc-8 (8.3.0-26ubuntu1~18.04) bionic-proposed; urgency=medium

  * SRU: LP: #1848319.
  * Backport GCC 8.3 8.3.0-26ubuntu1 to bionic.

gcc-8 (8.3.0-26ubuntu1) focal; urgency=medium

  * Merge with Debian; remaining changes:
    - Build from upstream sources.

gcc-8 (8.3.0-26) unstable; urgency=medium

  * Update to SVN 20191201 (r278885) from the gcc-8-branch.
    - Fix PR fortran/92100, PR fortran/92629, PR driver/89014.
  * Fix applying the gcc-linaro patch.
  * Stop building -dbg packages, keep building the libstc++6-8-dbg package
    containing just the libstdc++ debug build.

gcc-8 (8.3.0-25ubuntu4) focal; urgency=medium

  * Update to SVN 20191127 (r278756) from the gcc-8-branch.
    - Fix PR fortran/92100.
  * Stop building -dbg packages, keep building the libstc++6-8-dbg package
    containing just the libstdc++ debug build.

gcc-8 (8.3.0-25ubuntu2) focal; urgency=medium

  * Merge with Debian; remaining changes:
    - Build from upstream sources.
  * Fix applying the Linaro branch.

gcc-8 (8.3.0-25) unstable; urgency=medium

  * Update to SVN 20191126 (r278718) from the gcc-8-branch.
    - Fix PR c/91401, PR tree-optimization/91355, PR middle-end/90840,
      PR target/90867 (x86), PR c/90898, PR middle-end/91450,
      PR c++/92384, PR tree-optimization/92056, PR tree-optimization/91665,
      PR middle-end/91001, PR middle-end/91105, PR middle-end/91106,
      PR middle-end/91623, PR other/92090, PR target/92389 (x86),
      PR target/87833 (x86), PR target/92095 (SPARC), PR fortran/92113,
      PR tree-optimization/85887, PR c++/92201, PR c++/91974,
      PR preprocessor/92296, PR fortran/92569, PR ada/92575.

gcc-8 (8.3.0-24ubuntu1) focal; urgency=medium

  * Merge with Debian; remaining changes:
    - Build from upstream sources.

gcc-8 (8.3.0-24) unstable; urgency=medium

  * Update to SVN 20191107 (r277923) from the gcc-8-branch.
    - Fix PR target/91275 (PPC), PR fortran/84487, PR libstdc++/92143,
      PR libstdc++/92059, PR target/86487, PR target/65342 (PPC),
      PR target/70010 (PPC), PR target/88167 (ARM), PR debug/91887,
      PR tree-optimization/91812, PR debug/91772, PR tree-optimization/92131,
      PR target/86040 (AVR), PR rtl-optimization/89721, PR target/89400 (ARM),
      PR target/92022 (ALPHA), PR target/88630 (SH), PR c++/88075,
      PR c++/92106, PR ada/91995, PR fortran/86248, PR fortran/69455,
      PR rtl-optimization/85458, PR target/91289 (PPC).

gcc-8 (8.3.0-23ubuntu2) eoan; urgency=medium

  * Update to SVN 20191008 (r276700) from the gcc-8-branch.
    - Fix PR target/91275 (PPC), PR fortran/84487.

gcc-8 (8.3.0-23ubuntu1) eoan; urgency=medium

  * Merge with Debian; remaining changes:
    - Build from upstream sources.

gcc-8 (8.3.0-23) unstable; urgency=medium

  * Update to SVN 20191002 (r276439) from the gcc-8-branch.
    - Fix PR target/86712 (SH), PR target/88562 (SH), PR target/91854 (SPARC),
      PR target/80672 (SH), PR target/85993 (SH), PR rtl-optimization/88751,
      PR rtl-optimization/89795, PR fortran/91588, PR fortran/91550,
      PR fortran/91557.
  * Bump standards version.

gcc-8 (8.3.0-22ubuntu2...

Changed in gcc-8 (Ubuntu Bionic):
status: Fix Committed → Fix Released
status: Fix Committed → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.