Когда статический член в классе С++ является 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
он отлично работает. Инициализация элемента вручную в каждом потоке, который его использует (прокомментированная строка), решает проблему.
Это поведение undefined в соответствии со стандартом С++ или это может быть ошибка компилятора? Я попытался с gcc 7.1.1 и с 5.2.0, которые оба порождают ошибку. clang 3.8, похоже, работает.
Изменить: я подтвердил это поведение с помощью gcc 8.0.0 20170817 из SVN и представил отчет об ошибке: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81880