【发布时间】:2018-01-24 23:08:26
【问题描述】:
当 C++ 类中的静态成员既是 thread_local 又是成员模板时,它不会被初始化。
#include <unordered_map>
#include <iostream>
class A {
public:
template<typename T>
thread_local static std::unordered_map<int,T> m;
};
template<typename T>
thread_local std::unordered_map<int,T> A::m{};
int main() {
// A::m<int> = std::unordered_map<int,int>{}; // solves the problem
std::cout << A::m<int>.bucket_count() << std::endl; // returns zero.
A::m<int>.insert({1,2}); // causes SIGPFE (hash modulo bucket_count)
}
unordered_map 未初始化,存储桶计数为零。当哈希取模桶计数时,这会导致零除法。没有thread_local 或没有template 它工作正常。在每个使用它的线程中手动初始化成员(注释行)可以解决问题。
这是根据 C++ 标准的未定义行为还是编译器错误?我尝试使用 gcc 7.1.1 和 5.2.0 都产生错误。 clang 3.8 似乎可以工作。
编辑:我使用来自 SVN 的 gcc 8.0.0 20170817 确认了此行为并提交了错误报告:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81880
【问题讨论】:
-
对我来说似乎是一个明显的错误。你提交错误报告了吗?如果有,可以分享一下链接吗?
-
gcc (HEAD) 8... 也受此影响
-
我不认为这是一个错误。为什么您的应用程序会浪费时间为您创建的每个线程初始化数据,即使它不会使用它?线程本地存储由操作系统处理,而不是编译器。
-
@Michaël Roy 它是值初始化的(
A::m{};行)。这里的问题是 gcc 如何处理作为静态成员的模板变量的实例化,它在没有值初始化的情况下发生。 -
gcc 可以很好地处理模板静态变量的“常规”实例化。但是any线程局部变量需要线程局部初始化,因为操作系统需要使用该变量的实际线程为其分配一个槽,
标签: c++ multithreading c++14