Возможная ошибка компилятора clang с thread_local в шаблонах - PullRequest
0 голосов
/ 22 мая 2018

В моем проекте мне нужно отдельное локальное хранилище для каждого экземпляра элемента данных.Поскольку при реализации этой функции у меня возникли проблемы, я извлек упрощенную версию кода в следующую программу на C ++ 14:

#include <iostream>
#include <unordered_map>
#include <vector>

template<class T> class ThreadLocalMember
{
public:
    T& local() { return store.map[this]; }
private:
    struct Store
    {
        Store() { std::cout << "construct" << std::endl; }
        ~Store() { std::cout << "destruct" << std::endl; }
        std::unordered_map<ThreadLocalMember<T>*, T> map;
    };
    static thread_local Store store;
};

template <class T> thread_local typename ThreadLocalMember<T>::Store ThreadLocalMember<T>::store;

int main()
{
    ThreadLocalMember<int> counter;
    std::cout << "point 1" << std::endl;
    int result = counter.local();
    std::cout << "point 2; result: " << result << std::endl;
    return result;
}

Ожидаемый результат -

point 1
construct
point 2; result: 0
destruct

Однакопри компиляции с помощью clang Apple LLVM версии 9.1.0 (clang-902.0.39.1) на MacOS High Sierra 10.13.4 с использованием

clang++ -std=c++14 -O3 ThreadLocalMember.cpp -o test

(или с -O1 или -O2) вывод будет:

point 1
Illegal instruction: 4

Кажется, что конструктор переменной thread_local никогда не выполняется, и программа аварийно завершает работу при первом обращении к переменной.

Проблема исчезает, когда

  • программа компилируется без оптимизации (что недопустимо в производственном режиме)
  • класс шаблона заменяется обычным классом (возможный обходной путь, но очень раздражающий)
  • ключевое слово thread_localудалены в обоих местах (но тогда программа больше не делает то, что мне нужно, когда есть несколько потоков)

Программа также компилирует и запускает fКроме того, при использовании gcc 5.4.0 в Ubuntu 16 с флагом оптимизации или без него.

Что-то не так с моим кодом или я вижу ошибку компилятора clang?

...