C++ 为什么GCC 7.2 libstdc++;在CentOS 7上选择ABI?

C++ 为什么GCC 7.2 libstdc++;在CentOS 7上选择ABI?,c++,c++11,gcc,centos,c++14,C++,C++11,Gcc,Centos,C++14,我试图在CentOS 7上用GCC 7.2.1编译一个简单的程序。找到后,我使用以下命令在新的Docker CentOS映像上安装了g++: $ 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++ 确认安装: $ g++ -v Using built-in specs. COLLE

我试图在CentOS 7上用GCC 7.2.1编译一个简单的程序。找到后,我使用以下命令在新的Docker CentOS映像上安装了
g++

$ 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++
确认安装:

$ 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) 
正在尝试编译程序:

// 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;
}
给出以下编译器错误:

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> >}'
main.cpp:在函数“int main()”中:
main.cpp:9:79:错误:调用“std::basic_string::erase(_gnu_cxx::_normal_迭代器,std::basic_string::const_迭代器)”时没有匹配的函数
擦除(std::find(std::cbegin(foo),std::cend(foo),'1'),std::cend(foo));
^
在/opt/rh/devtoolset-7/root/usr/include/c++/7/string:52:0中包含的文件中,
来自main.cpp:1:
/opt/rh/devtoolset-7/root/usr/include/c++/7/bits/basic_string.h:4476:7:注:候选:std::basic_string&std::basic_string::erase(std::basic_string::size_type,std::basic_string::size_type)[带字符;_Traits=std::char Traits;_Alloc=std::分配器;std::basic_string::size_type=long unsigned int]
擦除(大小\类型\位置=0,大小\类型\ n=NPO)
^~~~~
/opt/rh/devtoolset-7/root/usr/include/c++/7/bits/basic_string.h:4476:7:注意:参数1从“u gnu_cxx::u normal_迭代器”到“std::basic_string::size_type{aka long unsigned int}”没有已知的转换
/opt/rh/devtoolset-7/root/usr/include/c++/7/bits/basic_string.h:4492:7:注意:候选:std::basic_string::iterator std::basic_string::erase(std::basic_string::iterator)[with(with)CharT=char;_Traits=std::char_Traits;_Alloc=std::分配器;std::basic_string::iterator=_gnu_cxx:::_normal_迭代器;typename _Alloc::rebind::other::pointer=char*]
擦除(迭代器位置)
^~~~~
/opt/rh/devtoolset-7/root/usr/include/c++/7/bits/basic_string.h:4492:7:注意:候选者需要1个参数,提供2个
/opt/rh/devtoolset-7/root/usr/include/c++/7/bits/basic_string.h:4512:7:注:候选:std::basic_string::iterator std::basic_string::erase(std::basic_string::iterator,std::basic_string::iterator)[with(with)CharT=char;_Traits=std::char_Traits;_Alloc=std::分配器;std::basic_string::iterator=_gnu_cxx:::_normal_迭代器;typename _Alloc::rebind::other::pointer=char*]
擦除(首先是迭代器,最后是迭代器);
^~~~~
/opt/rh/devtoolset-7/root/usr/include/c++/7/bits/basic_string.h:4512:7:注意:参数1从“u gnu cxx::u normal_iterator”到“std::basic_string::iterator{aka u gnu_cxx::u normal iterator}”没有已知的转换

据我所知,选择的是错误的。这个例子在Ubuntu 16上编译得很好。发生了什么事?

如前所述,devtoolset-7附带的gcc版本似乎默认忽略了RHEL6和7下的_GLIBCXX_USE_cx11_ABI标志。该行为可能已转发给centos。

如果是ABI问题,linker会抱怨的,不是编译器。可能是其他一些隐秘的内部错误。这一个看起来不错。你的
g++-v
?它可能是默认使用旧ABI构建的。@T.C.添加。我想问题是
——默认libstdcxx ABI=gcc4兼容
位?为什么这会设置为
gcc
7?因为但是,yum软件包认为默认使用旧的ABI是一个好主意。如果需要新的ABI,那么可以定义需要它的宏,或者构建自己的GCC。@不可计算libstdc++的旧的
std::string
实现,包括这个实现。有关问题,请参阅extra GCC/g++7.3,请参阅。。。。(编译后的代码将取决于
libstdc++.so.6->libstdc++.so.6.0.24
)。
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> >}'