You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MinGW编译下thread_local shared_ptr析构触发SIGSEGV问题咨询

MinGW下thread_local std::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(),程序可正常退出。

咨询问题

  1. 为何MinGW(或Windows库)会在析构前擦除线程本地存储?内存擦除应在析构之后执行才合理。另外join()是否触发了存储擦除操作?
  2. 该行为是否违反C++标准?按理解标准应禁止在析构前擦除内存,若理解有误请指正。

内容的提问来源于stack exchange,提问作者Antares

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 01:35:24