Consider the following code:
#include <sstream>
#include <thread>
int main() {
std::thread([&]() {
thread_local std::ostringstream oss;
static_cast<void>(oss); // Make sure 'oss' is initialized.
}).join();
}
I've tried the following scenario with two downstream compilers/debuggers:
g++ test.cpp -o test.exe -ggdb (the last key is optional).test.exe successfully.gdb -ex run -ex where -ex "set confirm off" -ex q test.exe (same as running gdb test.exe and typing run, where, q and confirming)Expected output: code runs and terminates successfully.
Actual result: code crashes somewhere around second thread termination.
I've tested it both with ancient g++.EXE (tdm-1) 4.9.2/gdb GNU gdb (GDB) 7.6.1 from TDM-GCC (it required additional -std=c++11), and with a very recent msys2 build: g++ (Rev10, Built by MSYS2 project) 10.2.0/GNU gdb (GDB) 10.1. The latter's output is as follows:
GNU gdb (GDB) 10.1
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-w64-mingw32".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from test.exe...
Starting program: F:\_0_MAIN\Teach\2020\cpp\drafts\210427\test.exe
warning: [doctest] doctest version is "2.4.6"
[doctest] run with "--help" for options
[New Thread 11556.0xb0]
warning: Critical error detected c0000374
Thread 2 received signal SIGTRAP, Trace/breakpoint trap.
[Switching to Thread 11556.0xb0]
0x00000000774cf680 in ntdll!RtlUnhandledExceptionFilter ()
from C:\Windows\SYSTEM32\ntdll.dll
#0 0x00000000774cf680 in ntdll!RtlUnhandledExceptionFilter ()
from C:\Windows\SYSTEM32\ntdll.dll
#1 0x00000000774cfc86 in ntdll!EtwEnumerateProcessRegGuids ()
from C:\Windows\SYSTEM32\ntdll.dll
#2 0x00000000774d08a2 in ntdll!RtlQueryProcessLockInformation ()
from C:\Windows\SYSTEM32\ntdll.dll
#3 0x00000000774d29b4 in ntdll!RtlLogStackBackTrace ()
from C:\Windows\SYSTEM32\ntdll.dll
#4 0x000000007743a0b0 in ntdll!RtlFreeHeap ()
from C:\Windows\SYSTEM32\ntdll.dll
#5 0x000007feff0310c8 in msvcrt!free () from C:\Windows\system32\msvcrt.dll
#6 0x000007feccd19827 in ?? ()
from C:\Software\msys64\mingw64\bin\libstdc++-6.dll
#7 0x000000013f9599a6 in run_dtor_list (ptr=<synthetic pointer>)
at C:/_/M/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/tls_atexit.c:59
#8 tls_callback (hDllHandle=<optimized out>, dwReason=<optimized out>,
lpReserved=<optimized out>)
at C:/_/M/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/tls_atexit.c:155
#9 0x0000000077455088 in ntdll!RtlpUnWaitCriticalSection ()
from C:\Windows\SYSTEM32\ntdll.dll
#10 0x000000007744868f in ntdll!LdrShutdownThread ()
from C:\Windows\SYSTEM32\ntdll.dll
#11 0x0000000077453ee8 in ntdll!RtlExitUserThread ()
from C:\Windows\SYSTEM32\ntdll.dll
#12 0x000007feff034213 in msvcrt!_endthreadex ()
from C:\Windows\system32\msvcrt.dll
#13 0x000007fef1394f6e in ?? ()
from C:\Software\msys64\mingw64\bin\libwinpthread-1.dll
#14 0x000007feff03415f in srand () from C:\Windows\system32\msvcrt.dll
#15 0x000007feff036ebd in msvcrt!_ftime64_s ()
from C:\Windows\system32\msvcrt.dll
#16 0x00000000772059cd in KERNEL32!BaseThreadInitThunk ()
from C:\Windows\system32\kernel32.dll
#17 0x000000007746383d in ntdll!RtlUserThreadStart ()
from C:\Windows\SYSTEM32\ntdll.dll
#18 0x0000000000000000 in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
the former's output is as follows:
GNU gdb (GDB) 7.6.1
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "mingw32".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from D:\home\yeputons\210427\test.exe...done.
Starting program: D:\home\yeputons\210427/test.exe
[New Thread 10004.0x1518]
[New Thread 10004.0x1f78]
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 10004.0x1f78]
0x00470deb in std::basic_ostringstream<char, std::char_traits<char>, std::allocator<char> >::~basic_ostringstream() ()
#0 0x00470deb in std::basic_ostringstream<char, std::char_traits<char>, std::allocator<char> >::~basic_ostringstream() ()
#1 0x00000001 in ?? ()
#2 0x00000000 in ?? ()
The first issue where I encountered this problem is https://github.com/onqtam/doctest/issues/501
P.S. Sorry, I've accidentally attached wrong stacktraces for gdb 10/gdb 10, here is a correct one:
Another datapoint: compiled on Ubuntu 20.04 with
g++-mingw-w64-x86-64 9.3.0-7ubuntu1+22~exp1ubuntu4(x86_64-w64-mingw32-g++-posixwith-staticand-static-libgccspecifically,-win32version does not supportstd::threadapparently) , ran on Windows, it crashed on thread termination even without gdb attached.A simpler example (testing with msys2's gcc 10.2.0/gdb 10.1):
Here
xin constructor is0x1234as expected, but it becomes0xFEEEFEEEFEEEFEEEbefore destructor is called, see attachedgdb-session-1.txtI was able to google up a very similar issue from 2017: https://github.com/msys2/MINGW-packages/issues/2519