【问题标题】:Thread sanitizer gives false negative for "function race"Thread sanitizer 对“函数竞赛”给出了假阴性
【发布时间】:2018-09-02 03:48:21
【问题描述】:

考虑以下代码:

#include <atomic>
#include <iostream>
#include <thread>

std::atomic<int> x, y;
std::atomic<int> r1, r2;

void f()
{
  r1 = y.load();
  x = r1.load();
}

void g()
{
  r2 = x.load();
  y = 42;
}

int main()
{
  x = 0;
  y = 0;
  r1 = 0;
  r2 = 0;

  std::thread t1(f);
  std::thread t2(g);

  t1.join();
  t2.join();

  std::cout << r1 << " " << r2 << std::endl;
}
  1. 如果我使用compilers/linux-x86_64-2.10.1/gnu7.1.0/bin/g++ -fsanitize=thread -O3 -std=c++11 main.cpp -o a.out 编译此代码,TSan 不会提供任何警告和/或线程错误。
  2. 但是,允许此代码生成42 00 0 作为输出。
    • 如果g()f() 开始之前执行,那么r1 = y.load() 的值为42
    • 如果在f() 开始之前未执行g(),则r1 = y.load() 的值为0
  3. 这是我应该期待TSan 捕捉到的东西,还是我的期望在这里完全错误?
    • 如果我的预期是错误的,可以做些什么(除了代码检查,这对于较大的代码库来说可能非常困难)来发现这样的错误?
    • 如果应该抛出一些错误,是否有一些我可能遗漏的特定选项(我正在使用文档here 中指定的所有默认值)?

【问题讨论】:

  • 你想要输出哪个?
  • @Jarod42:对于这种特殊情况,我并不特别关心特定的输出,我只想要Tsan(作为 Clang 的一部分提供的第三方库,并且被反向移植到GCC) 以提供指示潜在线程问题的错误消息。
  • 开放式问题:std::atomic&lt;T&gt; 确保读/写T 是原子的。是否允许编译器重新排序 f()g() 的语句,因为它们不相互依赖? (所有变量都是42
  • 来自github.com/google/sanitizers/wiki/ThreadSanitizerCppManual: "ThreadSanitizer (aka TSan) 是 C/C++ 的数据竞争检测器。" 这里没有数据竞争,绝不可能您的一个变量可以同时被两个线程访问。如果要确保操作顺序,请使用std::memory_order

标签: c++ thread-sanitizer


【解决方案1】:

来自clang's documentation

ThreadSanitizer 是一种检测数据竞争的工具

您没有数据竞争,因为您的所有变量都是原子的,因此无需报告。

【讨论】:

  • @Holt:这是数据竞争,而不是竞争条件。两者是不同的,请参阅,例如,here
  • @R_Kapp 该工具只检测数据竞争,而不是竞争条件。
  • @R_Kapp ThreadSanitizer 只检测数据竞争,而不是一般竞争条件。您是对的,两者是不同的,但您也误解了 ThreadSanitizer 的作用范围。
  • @AlexanderHuszagh:很公平。我不知道我从哪里知道它当时也有比赛条件......可能只是一厢情愿。
  • 稍微澄清一下:C++ 语言定义使用术语“数据竞争”;这意味着两个或多个线程可以同时访问同一个存储区域,并且至少其中一个会修改它。 std::atomic 防止同时访问,因此没有标准定义的“数据竞争”。这并不能保证程序的行为是完全确定的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-10-27
  • 1970-01-01
  • 2017-03-30
  • 1970-01-01
  • 1970-01-01
  • 2010-10-02
  • 1970-01-01
相关资源
最近更新 更多