【发布时间】:2017-11-10 15:48:52
【问题描述】:
这段代码:
#include <iostream>
#include <thread>
#include <mutex>
struct Singl{
Singl(Singl const&) = delete;
Singl(Singl&&) = delete;
inline static thread_local bool alive = true;
Singl(){
std::cout << "Singl() " << std::this_thread::get_id() << std::endl;
}
~Singl(){
std::cout << "~Singl() " << std::this_thread::get_id() << std::endl;
alive = false;
}
};
static auto& singl(){
static thread_local Singl i;
return i;
}
struct URef{
~URef(){
const bool alive = singl().alive;
std::cout << alive << std::endl;
}
};
int main() {
std::thread([](){
singl();
static thread_local URef u;
}).join();
return 0;
}
有以下输出:
Singl() 2
Singl() 2
1
~Singl() 2
~Singl() 2
我正在使用 mingw-w64 gcc7.2 POSIX 线程在 Windows 下编译和运行。
Coliru 有不同的输出: http://coliru.stacked-crooked.com/a/3da415345ea6c2ee
这是什么?我的工具链/编译器有问题,还是应该这样?为什么我在同一个线程上有两个 thread_local 对象(或构造了两次?)?
【问题讨论】:
-
我建议在调试器中运行它,在
Singl构造函数中放置一个断点,并在每次遇到断点时查看堆栈跟踪。这应该会给你一个关于发生了什么的线索。 -
已经完成 - 不知道......所有 mingw-w64 gcc 7.x 的行为相同。 VS2017 的输出与 coliru 相同。
-
@tower120 那么做堆栈跟踪是什么样的?
-
FWIW VS2015 只构造一次
Singl。 -
在 ~URef() 中构造的第二个 Singl,constor 本身由神秘的 TLS 包装器 __tls_init 调用。然后两个析构函数都调用线程销毁。
标签: c++ gcc thread-safety mingw-w64 thread-local-storage