When a static member in a C++ class is both thread_local
and a member template, it doesn't get initialised.
#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)
}
The unordered_map is not initialised and has a bucket count of zero. This leads to a zero division when the hash is taken modulo the bucket count. Without the thread_local
or without the template
it works fine. Initialising the member manually in every thread which uses it (commented line) solves the problem.
Is this undefined behaviour according to the C++ standard or could this be a compiler bug? I tried with gcc 7.1.1 and with 5.2.0 which both produce the error. clang 3.8 seems to work.
Edit: I confirmed this behaviour with gcc 8.0.0 20170817 from SVN and submitted a bug report: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81880