MinGW编译下thread_local shared_ptr析构触发SIGSEGV问题咨询
问题概述
使用thread_local std::shared_ptr管理线程本地访问对象时,在Windows10环境下通过MinGW编译后,线程调用join()并析构thread_local的shared_ptr时会触发SIGSEGV。该程序在Linux gcc/clang、Windows MSVC编译环境下均可正常运行。
复现代码
// main.cpp #include <memory> #include <thread> void f() { thread_local std::shared_ptr<int> ptr = std::make_shared<int>(0); } int main() { std::thread th(f); th.join(); return 0; }
编译信息
编译命令:
g++ main.cpp -o build\main.exe -std=c++17
编译器版本:
>g++ --version g++ (x86_64-posix-seh-rev2, Built by MinGW-W64 project) 12.2.0 Copyright (C) 2022 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
调试结果
使用gdb运行时,主线程等待join()期间,新线程触发SIGSEGV。调试发现,调用RtlpWow64SetContextOnAmd64时,包含thread_local shared_ptr的连续内存段在析构前被擦除为0xfeeefeee,后续shared_ptr执行析构时读取该值触发SIGSEGV。
调用栈:
RtlpWow64SetContextOnAmd64 0x00007ffd8f4deb5f RtlpWow64SetContextOnAmd64 0x00007ffd8f4de978 SbSelectProcedure 0x00007ffd8f4ae2e0 CloseHandle 0x00007ffd8ce3655b pthread_create_wrapper 0x00007ffd73934bac _beginthreadex 0x00007ffd8e9baf5a _endthreadex 0x00007ffd8e9bb02c BaseThreadInitThunk 0x00007ffd8ec87614 RtlUserThreadStart 0x00007ffd8f4c26a1
对应的汇编代码片段:
... mov %rax,(%rdi) movdqu %xmm0,(%rsi) ; <------ 此处执行擦除 call 0x7ffd8f491920 ; <ntdll!RtlReleaseSRWLockShared> mov $0x1,%r9d mov 0x30(%rsp),%rbx ...
另外发现,若将join()替换为detach(),程序可正常退出。
咨询问题
- 为何MinGW(或Windows库)会在析构前擦除线程本地存储?内存擦除应在析构之后执行才合理。另外
join()是否触发了存储擦除操作? - 该行为是否违反C++标准?按理解标准应禁止在析构前擦除内存,若理解有误请指正。
内容的提问来源于stack exchange,提问作者Antares
相关产品推荐
相关产品推荐

