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

            Bug ID: 93050
           Summary: throw within constructor initialisation list causes
                    invalid free in destructor
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: db0451 at gmail dot com
  Target Milestone: ---

I've come across this error at least twice when trying to throw from
constructor initialisation lists, so I don't *think* I'm uniquely at fault
here...

All I want to do is move/copy an argument into a member if suitable, and throw
if not, while not having to use the constructor body, instead the ctor
init-list

The below code, compiled with...

* g++ --version: `g++.exe (Rev2, Built by MSYS2 project) 9.2.0`
* compiler args: `g++ -std=c++17 -Wall -Wextra -Wpedantic test.cpp`

...correctly throws when Test() is called with an empty string, but with a
non-empty string is crashes in free() via ~Test().

source:

```cpp
#include <stdexcept>
#include <string>

struct Test final {
        std::string m_string;

        Test(std::string string)
        : m_string{ !string.empty() ? std::move(string)
                    : throw std::invalid_argument{"string cannot be empty"} }
        {}
};

auto
main() -> int
{
        auto test = Test{"2"};
        return 0;
}
```

gdb log, run on 

```
Reading symbols from ./a.exe...done.
(gdb) run
Starting program: /tmp/Atm/build/a.exe
[New Thread 3880.0x3c38]
[New Thread 3880.0x2b68]
[New Thread 3880.0x5624]
[New Thread 3880.0x4a14]
warning: Critical error detected c0000374

Thread 1 received signal SIGTRAP, Trace/breakpoint trap.
0x00007ffdca4391f3 in ntdll!RtlIsNonEmptyDirectoryReparsePointAllowed () from
/c/WINDOWS/SYSTEM32/ntdll.dll
(gdb) bt
#0  0x00007ffdca4391f3 in ntdll!RtlIsNonEmptyDirectoryReparsePointAllowed ()
from /c/WINDOWS/SYSTEM32/ntdll.dll
#1  0x00007ffdca441622 in ntdll!RtlpNtMakeTemporaryKey () from
/c/WINDOWS/SYSTEM32/ntdll.dll
#2  0x00007ffdca44192a in ntdll!RtlpNtMakeTemporaryKey () from
/c/WINDOWS/SYSTEM32/ntdll.dll
#3  0x00007ffdca44a8e9 in ntdll!RtlpNtMakeTemporaryKey () from
/c/WINDOWS/SYSTEM32/ntdll.dll
#4  0x00007ffdca38088d in ntdll!RtlGetCurrentServiceSessionId () from
/c/WINDOWS/SYSTEM32/ntdll.dll
#5  0x00007ffdca37fc11 in ntdll!RtlFreeHeap () from
/c/WINDOWS/SYSTEM32/ntdll.dll
#6  0x00007ffdc8fd9cfc in msvcrt!free () from /c/WINDOWS/System32/msvcrt.dll
#7  0x0000000000402ef8 in Test::~Test() ()
#8  0x00000000004015d2 in main ()
(gdb)
```

Copying instead of `std::move()`ing the `string` doesn't seem to change
anything

Moving the check/throw into the constructor body works but shouldn't be needed.

Reply via email to