32

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

maiphi
  • 461
  • 3
  • 9
  • 3
    Seems like a clear bug to me. Did you submit a bugreport? If you did, can you please share the link? – SergeyA Aug 16 '17 at 19:14
  • gcc (HEAD) 8... is affected by this too – Swift - Friday Pie Aug 18 '17 at 16:39
  • 1
    I don't think it's a bug. Why would your app waste time initializing data for every thread you create even if it will not use it? Thread-local storage is handled by the OS, and not by the compiler. – Michaël Roy Aug 19 '17 at 07:47
  • @Michaël Roy it is value initialized (`A::m{};` line). The problem here is how gcc handles instantiation of template variable that is a static member, it happens without value initialization. – Swift - Friday Pie Aug 23 '17 at 06:50
  • 1
    gcc handles 'regular' instantiation of template static variables just fine. But _any_ thread-local variable needs thread-local initialization, since the OS requires the actual thread that uses the variable to allocate a slot for it, – Michaël Roy Aug 23 '17 at 14:34
  • You should add a link to your bug report as an answer and select it as your answer so this drops off the 'unanswered question' list. – Omnifarious Nov 30 '17 at 15:29

1 Answers1

4

Once again, to close the question: I submitted a bug report, see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81880

maiphi
  • 461
  • 3
  • 9