匿名命名空间中的struct的thread_local模板变量无法链接?

时间:2019-04-10 23:03:24

标签: c++ gcc compiler-errors compilation clang

以下示例程序使用线程局部模板变量,并使用匿名名称空间中的类型实例化该变量。这会在gcc中产生链接器错误。在clang中,它实际上可以编译,但不能正确运行。

#include <stdio.h>

template<typename T>
struct container {
    container()  { printf("construct: %p\n", this); }
    ~container() { printf("destruct: %p\n", this);  }
};

template<typename T>
thread_local container<T> storage;

namespace {
    struct bar {};
}

int main() {
    auto& ref1 = storage<bar>;
    auto& ref2 = storage<bar>;
}

在gcc上,此操作失败并出现链接错误:

a.cpp:6:2: warning: ‘container<T>::~container() noexcept [with T = {anonymous}::bar]’ used but never defined
  ~container() { printf("destruct: %p\n", this);  }
  ^
/tmp/ccgh0P15.o: In function `__tls_init':
a.cpp:(.text+0xa9): undefined reference to `container<(anonymous namespace)::bar>::~container()'

使用clang程序可以编译,但是会产生令人不安的输出:

construct: 0x7fb8d1c003d0
construct: 0x7fb8d1c003d0
destruct: 0x7fb8d1c003d0
destruct: 0x7fb8d1c003d0

我在这里遇到的围绕thread_local / templated变量是否存在一些粗糙的边缘?我不清楚为什么这会产生链接错误(如果删除thread_local,链接错误会消失)。在clang的情况下,具有静态存储持续时间的对象的双重破坏怎么可能只是编译器错误?在clang中,如果我删除匿名名称空间或thread_local规范,或者通过删除main()中的引用之一,问题就会消失。

任何人都可以阐明这一点,我主要是想知道我是否误解了什么。谢谢!

编辑:

clang++ -v

Apple LLVM version 10.0.0 (clang-1000.11.45.5)

g++ -v

gcc version 7.3.0 (Ubuntu 7.3.0-27ubuntu1~18.04)

0 个答案:

没有答案