4

I'm trying to compile a simple program with GCC 7.2.1 on CentOS 7. After finding this package, I installed g++ with the following command on a fresh Docker CentOS image:

$ yum install centos-release-scl-rh
$ yum install devtoolset-7-gcc-c++
$ ln -s /opt/rh/devtoolset-7/root/usr/bin/g++ /usr/local/bin/g++

Confirming the install:

$ g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/opt/rh/devtoolset-7/root/usr/libexec/gcc/x86_64-redhat-linux/7/lto-wrapper
Target: x86_64-redhat-linux
Configured with: ../configure --enable-bootstrap --enable-languages=c,c++,fortran,lto --prefix=/opt/rh/devtoolset-7/root/usr --mandir=/opt/rh/devtoolset-7/root/usr/share/man --infodir=/opt/rh/devtoolset-7/root/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-gcc-major-version-only --enable-plugin --with-linker-hash-style=gnu --enable-initfini-array --with-default-libstdcxx-abi=gcc4-compatible --with-isl=/builddir/build/BUILD/gcc-7.2.1-20170829/obj-x86_64-redhat-linux/isl-install --enable-libmpx --enable-gnu-indirect-function --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux
Thread model: posix
gcc version 7.2.1 20170829 (Red Hat 7.2.1-1) (GCC) 

Attempting to compile the program:

// main.cpp
#include <string>
#include <iterator>
#include <algorithm>
#include <iostream>

int main()
{
    std::string foo {"hello world10m"};
    foo.erase(std::find(std::cbegin(foo), std::cend(foo), '1'), std::cend(foo));
    std::cout << foo << std::endl;
}

using the command:

$ g++ -std=gnu++14 -o test main.cpp

gives the following compiler error:

main.cpp: In function 'int main()':
main.cpp:9:79: error: no matching function for call to 'std::basic_string<char>::erase(__gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >, std::basic_string<char>::const_iterator)'
     foo.erase(std::find(std::cbegin(foo), std::cend(foo), '1'), std::cend(foo));
                                                                               ^
In file included from /opt/rh/devtoolset-7/root/usr/include/c++/7/string:52:0,
                 from main.cpp:1:
/opt/rh/devtoolset-7/root/usr/include/c++/7/bits/basic_string.h:4476:7: note: candidate: std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::erase(std::basic_string<_CharT, _Traits, _Alloc>::size_type, std::basic_string<_CharT, _Traits, _Alloc>::size_type) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>; std::basic_string<_CharT, _Traits, _Alloc>::size_type = long unsigned int]
       erase(size_type __pos = 0, size_type __n = npos)
       ^~~~~
/opt/rh/devtoolset-7/root/usr/include/c++/7/bits/basic_string.h:4476:7: note:   no known conversion for argument 1 from '__gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >' to 'std::basic_string<char>::size_type {aka long unsigned int}'
/opt/rh/devtoolset-7/root/usr/include/c++/7/bits/basic_string.h:4492:7: note: candidate: std::basic_string<_CharT, _Traits, _Alloc>::iterator std::basic_string<_CharT, _Traits, _Alloc>::erase(std::basic_string<_CharT, _Traits, _Alloc>::iterator) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>; std::basic_string<_CharT, _Traits, _Alloc>::iterator = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >; typename _Alloc::rebind<_CharT>::other::pointer = char*]
       erase(iterator __position)
       ^~~~~
/opt/rh/devtoolset-7/root/usr/include/c++/7/bits/basic_string.h:4492:7: note:   candidate expects 1 argument, 2 provided
/opt/rh/devtoolset-7/root/usr/include/c++/7/bits/basic_string.h:4512:7: note: candidate: std::basic_string<_CharT, _Traits, _Alloc>::iterator std::basic_string<_CharT, _Traits, _Alloc>::erase(std::basic_string<_CharT, _Traits, _Alloc>::iterator, std::basic_string<_CharT, _Traits, _Alloc>::iterator) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>; std::basic_string<_CharT, _Traits, _Alloc>::iterator = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >; typename _Alloc::rebind<_CharT>::other::pointer = char*]
       erase(iterator __first, iterator __last);
       ^~~~~
/opt/rh/devtoolset-7/root/usr/include/c++/7/bits/basic_string.h:4512:7: note:   no known conversion for argument 1 from '__gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >' to 'std::basic_string<char>::iterator {aka __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >}'

As far as I can tell, the wrong libstdc++ ABI is being selected. This example compiles fine on Ubuntu 16. What's going on?

Daniel
  • 8,179
  • 6
  • 31
  • 56
  • 1
    If it would be ABI problem, linker would complain, not compiler. And may be some other cryptic internal errors. This one looks fine. – Incomputable Dec 20 '17 at 18:25
  • What's your `g++ -v`? It's probably built to use the old ABI by default. – T.C. Dec 20 '17 at 18:33
  • 1
    @T.C. Added. I guess the problem is the `--with-default-libstdcxx-abi=gcc4-compatible` bit? Why would this be set on `gcc` 7? – Daniel Dec 20 '17 at 19:01
  • Because whoever maintains the yum package decided that defaulting to the old ABI is a good idea. If you want the new ABI, then either define the macro asking for it or build your own GCC. – T.C. Dec 21 '17 at 01:26
  • 1
    @Incomputable libstdc++'s old `std::string` implementation [doesn't meet some C++11 requirements](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81967), including this one. – T.C. Dec 21 '17 at 01:27

1 Answers1

3

as stated here, it looks the version of gcc that ships with the devtoolset-7 silently ignores the _GLIBCXX_USE_CXX11_ABI flag under RHEL6 and 7. The behavior has been probably forwarded to centos.

  • see https://stackoverflow.com/questions/49393888/how-can-i-use-the-new-c-11-abi-with-devtoolset-7-on-centos-rhel for a related issue – Jean-Mathieu Vermosen Oct 04 '19 at 14:12
  • 1
    Extra gcc/g++ 7.3, see https://stackoverflow.com/questions/47175706/how-to-install-gcc-4-9-2-on-rhel-7-4/47189915#47189915 .... ( The compiled code will depend on `libstdc++.so.6 -> libstdc++.so.6.0.24` ). – Knud Larsen Oct 08 '19 at 11:46