这个简单的 C++ 代码中的数据竞争在哪里

Ozg*_*rat 16 c++ thread-sanitizer ubsan

clang++和消毒剂都会g++针对这个简单代码的数据竞争产生类似的警告。难道是虚惊一场?问题是什么?

代码:

#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;
}
Run Code Online (Sandbox Code Playgroud)

编译标志:

-pthread -O0 -g -fsanitize=thread -fsanitize=undefined
Run Code Online (Sandbox Code Playgroud)

消毒剂输出g++:

==================
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
Run Code Online (Sandbox Code Playgroud)

注意:仅当线程和 UB 消毒器同时启用时才会发出此警告。

use*_*522 12

该程序格式良好。它没有任何数据竞争或其他未定义的行为,也没有任何竞争条件或未指定的行为(如果线程创建失败,可能会因未捕获的异常而中止)。

线程清理程序根本无法与未定义的行为清理程序很好地配合。我不确定它们是否可以一起使用。我以前在组合它们时遇到过类似的问题,因此建议不要这样做。

如果他们注定要一起玩得很好,那么这确实是一个错误。

  • 我在 Xcode 方案设置 GUI 上进行了试用。Xcode 允许您选择地址和未定义行为清理程序,或线程和未定义行为清理程序。但地址和线程消毒剂不能一起使用。这似乎表明 OP 用例是合法的。 (2认同)