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

这段简单C++代码的数据竞态在哪?是否为误报?

ThreadSanitizer与UBSanitizer同时启用时的竞态警告是否为误报?

clang和g的Sanitizer针对以下简单C++代码均报告类似的数据竞态警告,仅当同时启用Thread Sanitizer和UB Sanitizer时才会出现此警告。请问这是否属于误报?问题出在哪里?

测试代码

#include <thread>
struct A
{
    void operator()()
    {
    }
};

struct B
{
    void operator()()
    {
    }
};

int main(void)
{
    // callable objects are created and moved into thread
    std::thread t1(A{});
    std::thread t2(B{});
    t1.join();
    t2.join();
    return 0;
}

编译选项

-pthread -O0 -g -fsanitize=thread -fsanitize=undefined

g++的Sanitizer输出

==================
WARNING: ThreadSanitizer: data race (pid=80173)
  Write of size 8 at 0x7b0400000800 by thread T2:
    #0 pipe ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:1726 (libtsan.so.0+0x3ea28)
    #1 __sanitizer::IsAccessibleMemoryRange(unsigned long, unsigned long) ../../../../src/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cpp:276 (libubsan.so.1+0x20102)
    #2 std::thread::_State_impl<std::thread::_Invoker<std::tuple<B> > >::~_State_impl() /usr/include/c++/11/bits/std_thread.h:201 (a.out+0x5191)
    #3 <null> <null> (libstdc++.so.6+0xdc2cb)

  Previous write of size 8 at 0x7b0400000800 by thread T1:
    #0 pipe ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:1726 (libtsan.so.0+0x3ea28)
    #1 __sanitizer::IsAccessibleMemoryRange(unsigned long, unsigned long) ../../../../src/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cpp:276 (libubsan.so.1+0x20102)
    #2 std::thread::_State_impl<std::thread::_Invoker<std::tuple<A> > >::~_State_impl() /usr/include/c++/11/bits/std_thread.h:201 (a.out+0x53a5)
    #3 <null> <null> (libstdc++.so.6+0xdc2cb)

  Thread T2 (tid=80176, running) created by main thread at:
    #0 pthread_create ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:969 (libtsan.so.0+0x605b8)
    #1 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) <null> (libstdc++.so.6+0xdc398)
    #2 main a.cpp:20 (a.out+0x3396)

  Thread T1 (tid=80175, finished) created by main thread at:
    #0 pthread_create ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:969 (libtsan.so.0+0x605b8)
    #1 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) <null> (libstdc++.so.6+0xdc398)
    #2 main a.cpp:19 (a.out+0x3383)

SUMMARY: ThreadSanitizer: data race ../../../../src/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cpp:276 in __sanitizer::IsAccessibleMemoryRange(unsigned long, unsigned long)
==================
ThreadSanitizer: reported 1 warnings

解答

这属于工具组合使用导致的误报,问题根源在Sanitizer库内部:

  • 当同时启用ThreadSanitizer(TSan)和UndefinedBehaviorSanitizer(UBSan)时,UBSan的IsAccessibleMemoryRange函数会调用pipe系统调用,而TSan会追踪所有内存操作。
  • 两个线程在销毁各自std::thread的内部状态时,都会触发UBSan的内存可达性检查,进而调用pipe。TSan误将pipe内部的共享内存操作识别为用户代码的数据竞态,但实际上这是Sanitizer库自身的共享资源访问未做同步保护导致的,和用户编写的代码完全无关。
  • 只有同时启用两个Sanitizer才会触发该警告,也进一步说明这是工具组合的内部问题,而非用户代码存在数据竞态。

内容的提问来源于stack exchange,提问作者Özgür Murat Sağdıçoğlu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 05:18:18