You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

模板中thread_local相关的Clang编译器疑似Bug咨询

Thread-Local Static Template Member Constructor Not Executing on Clang (MacOS) with Optimizations

Let's break down what's happening here and address your question directly.

First, let's recap your scenario with the relevant code and behavior:

Your Simplified Code

#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;
}

Expected Output

point 1
construct
point 2; result: 0
destruct

Actual Output (Clang on MacOS with -O1/-O2/-O3)

point 1
Illegal instruction: 4

Analysis & Conclusion

This is almost certainly a Clang compiler bug on MacOS when optimizing template classes with thread_local static members. Here's why:

Per the C++14 standard, thread_local static variables must be initialized the first time they are accessed by a thread. In your code, calling counter.local() should trigger the initialization of ThreadLocalMember<int>::store (and thus run the Store constructor) before accessing store.map.

GCC correctly handles this initialization even with optimizations enabled, but Clang (specifically Apple LLVM 9.1.0) appears to optimize away the initialization step when the thread_local member is part of a template class. The "Illegal instruction" crash happens because you're accessing the unordered_map in an uninitialized Store instance—its internal structures are garbage, leading to invalid memory operations.

Your observed workarounds confirm this:

  • Disabling optimizations removes the aggressive logic that breaks initialization.
  • Using a non-template class works because Clang handles non-template thread_local static members correctly.
  • Removing thread_local eliminates the thread-specific initialization logic entirely (but obviously breaks your multi-threading requirements).

Workaround

A simple fix to force Clang to initialize the store member is to explicitly reference it before accessing the map, which prevents the optimizer from eliding the initialization:

T& local() {
    (void)store; // Explicitly reference store to trigger construction
    return store.map[this];
}

This forces the compiler to initialize store before accessing map, which should resolve the crash while keeping your thread-local behavior intact.

内容的提问来源于stack exchange,提问作者Peter Camps

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:19:49