https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86138

--- Comment #6 from Christian Franke <franke at computer dot org> ---
(In reply to Jonathan Wakely from comment #4)
> Could you please debug this to find where it's crashing and why?

It segfaults with a bogus pointer below std::string::_Rep::_M_dispose().
A comparison of assembly output and object file symbols leads to the root of
the problem:

1) -std=c++14: string::string() and getline() are called from cygstdc++6.dll. 
OK.

2) -std=c++17: getline() is called from cygstdc++6.dll.  All code for
string::string() is part of the executable.  The empty string is initialized
with the static std::string::_Rep::_S_empty_rep_storage[] from the executable. 
But getline() uses the string() implementation from the DLL which checks
against the DLL version of _S_empty_rep_storage[] here:

   _M_dispose(const _Alloc& __a) _GLIBCXX_NOEXCEPT
   {
#if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
     if (__builtin_expect(this != &_S_empty_rep(), false))
#endif
     { ... }

This finally results in a bogus delete[] of the _S_empty_rep_storage[] from the
executable.

2) -std=c++17 -static: The linker does not pull another _S_empty_rep_storage[]
from the static library because it already exists in the object file.  OK.

This version of the testcase does not crash because _S_empty_rep_storage[] is
not used:

int main()
{
    std::string line("x");
    std::istringstream stream("*");
    std::getline(stream, line, '\n');
    return (int)line.c_str()[0];
}

Reply via email to