https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87520
Bug ID: 87520 Summary: [8/9 Regression] ODR violations in std::make_shared when mixing -fno-rtti and -frtti Product: gcc Version: 8.2.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: redi at gcc dot gnu.org Target Milestone: --- cat > main.cc << EOT #include <memory> extern int f(); // For the purposes of this demo, force a non-weak definition of // _Sp_counted_ptr_inplace::_M_get_deleter(const type_info&) to be emitted // in this translation unit: template class std::_Sp_counted_ptr_inplace<int, std::allocator<int>, std::_S_atomic>; int main() { return f(); } EOT cat > sp.cc << EOT #include <memory> int f() { return *std::make_shared<int>(); } EOT g++ -fno-rtti main.cc -c -g g++ -frtti sp.cc -c -g g++ main.o sp.o ./a.out This crashes: Segmentation fault (core dumped) The problem is that the definition of _Sp_counter_ptr_inplace::_M_get_deleter that the linker chooses was compiled with -fno-rtti but the caller was compiled with -frtti. The caller passes typeid(_Sp_make_shared_tag) which does not match the expected value in _M_get_deleter, so a null pointer is returned. That leaves the new shared_ptr holding a null pointer, so dereferencing it in f() crashes. This crash happens for all versions. A nastier failure happens with gcc-8 and trunk if we swap which object is built with RTTI and which without: g++ -frtti main.cc -c -g g++ -fno-rtti sp.cc -c -g g++ main.o sp.o ./a.out This crashes earlier, during construction of the shared_ptr: Program received signal SIGSEGV, Segmentation fault. 0x00000000004008cb in std::type_info::operator== (this=0x401700 <std::_Sp_make_shared_tag::_S_ti()::__tag>, __arg=...) at /home/jwakely/gcc/8/include/c++/8.2.1/typeinfo:123 (gdb) bt #0 0x00000000004008cb in std::type_info::operator== (this=0x401700 <std::_Sp_make_shared_tag::_S_ti()::__tag>, __arg=...) at /home/jwakely/gcc/8/include/c++/8.2.1/typeinfo:123 #1 0x0000000000400a31 in std::_Sp_counted_ptr_inplace<int, std::allocator<int>, (__gnu_cxx::_Lock_policy)2>::_M_get_deleter (this=0x615e70, type_info node=...) at /home/jwakely/gcc/8/include/c++/8.2.1/bits/shared_ptr_base.h:569 #2 0x0000000000401264 in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::_M_get_deleter (this=0x7fffffffd858, type_info node=...) at /home/jwakely/gcc/8/include/c++/8.2.1/bits/shared_ptr_base.h:749 #3 0x00000000004010ba in std::__shared_ptr<int, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator<int>>(std::_Sp_make_shared_tag, std::allocator<int> const&) (this=0x7fffffffd850, __tag=..., __a=...) at /home/jwakely/gcc/8/include/c++/8.2.1/bits/shared_ptr_base.h:1329 #4 0x0000000000401055 in std::shared_ptr<int>::shared_ptr<std::allocator<int>>(std::_Sp_make_shared_tag, std::allocator<int> const&) (this=0x7fffffffd850, __tag=..., __a=...) at /home/jwakely/gcc/8/include/c++/8.2.1/bits/shared_ptr.h:360 #5 0x0000000000400f8a in std::allocate_shared<int, std::allocator<int>>(std::allocator<int> const&) (__a=...) at /home/jwakely/gcc/8/include/c++/8.2.1/bits/shared_ptr.h:707 #6 0x0000000000400ed5 in std::make_shared<int> () at /home/jwakely/gcc/8/include/c++/8.2.1/bits/shared_ptr.h:723 #7 0x0000000000400d80 in f () at sp.cc:5 #8 0x000000000040089b in main () at main.cc:13 This is due to the fix for PR 80285. The __shared_ptr constructor is built without RTTI so calls _M_get_deleter(_Sp_make_shared_tag::_S_ti()). The definition of _M_get_deleter is built with RTTI so expects a real typeinfo object. When accessing the fake _S_ti() typeinfo object we crash, because it's an invalid reference that isn't bound to a real typeinfo.