标签: thread-sanitizer

此线程清洁工具警告中的种族在哪里?

在macOS上使用线程清理程序运行时,以下代码会产生警告。我看不到比赛在哪里。shared_ptr和weak_ptr的控制块是线程安全的,并且std::queue通过保持锁定来完成从中推入和弹出操作。

#include <future>
#include <memory>
#include <queue>

class Foo {
public:
  Foo() {
    fut = std::async(std::launch::async, [this] {
      while (!shouldStop) {
        std::scoped_lock lock(mut);
        while (!requests.empty()) {
          std::weak_ptr<float> requestData = requests.front();
          requests.pop();
          (void)requestData;
        }
      }
    });
  }

  ~Foo() {
    shouldStop.store(true);
    fut.get();
  }

  void add(const std::weak_ptr<float> subscriber) {
    std::scoped_lock lock(mut);
    requests.push(subscriber);
  }

private:
  std::atomic<bool> shouldStop = false;
  std::future<void> fut;
  std::queue<std::weak_ptr<float>> requests;
  std::mutex mut;
};

int main() {
  Foo foo;

  int numIterations = 100000;

  while (--numIterations) {
    auto subscriber = std::make_shared<float>(); …
Run Code Online (Sandbox Code Playgroud)

c++ multithreading shared-ptr weak-ptr thread-sanitizer

7
推荐指数
1
解决办法
108
查看次数

如何使螺纹清洁剂“更准确”?

根据线程消毒剂文档

ThreadSanitizer 使用比本机运行更多的实际内存。在默认设置下,每个线程的内存开销是 5 倍加 1Mb。还提供 3x(不太准确的分析)和 9x(更准确的分析)开销的设置。

我该如何选择这些设置?找不到它们的命令行参数。

c++ clang thread-safety clang++ thread-sanitizer

6
推荐指数
0
解决办法
128
查看次数

无法在Xcode 10.2中的模拟器上运行iOS应用

在Xcode 10.2中,我无法再在启用了线程清理程序的模拟器上运行我的应用程序。我得到错误

目前无法安装此应用。

WatchKit v3应用禁止使用Info.plist密钥:NSBuiltWithThreadSanitizer

我的应用程序包含一个监视应用程序和许多框架(一些用于监视,一些用于iOS),但是在尝试在模拟器上运行应用程序时出现此错误。我检查了plist文件,并确认这不是我在任何地方指定的密钥。

当我检查DerivedData中的plist文件时,我确实看到我的watch OS框架的所有复制人都具有此密钥。但是我发现删除标志的唯一方法是完全禁用线程清理程序。如何仅针对手表而不是我的主应用禁用它?

xcode ios thread-sanitizer

6
推荐指数
1
解决办法
395
查看次数

如何检测 gcc 5 的线程清理程序

如何检测使用 gcc 5 的构建是否已打开线程清理程序?两者之间的任何一个__has_feature(thread_sanitizer)都不__SANITIZE_THREAD__工作

#include <iostream>

using std::cout;
using std::endl;

int main() {
    cout << __has_feature(thread_sanitizer) << endl;
    cout << __SANITIZE_THREAD__ << endl;
}
Run Code Online (Sandbox Code Playgroud)

https://wandbox.org/permlink/t5qYme4Whyj54aYV。这在具有线程清理程序的 clang 版本上进行编译;但不适用于某些 gcc 版本(特别是 5)


功能检查和__SANITIZE_THREAD__宏都可用于检测线程清理程序何时打开,因此测试可以抑制误报(例如,当线程清理程序捕获实际上不是数据争用的错误时)请参阅了解更多信息

c++ gcc thread-sanitizer c++14

6
推荐指数
1
解决办法
1538
查看次数

如何避免或抑制此无锁堆栈中的竞争?

我正在使用无锁堆栈(通过标记指针)来管理小内存块池。当块被插入到池中和从池中移除时,列表节点就地创建和销毁。

这是一个非常简化的测试程序,它只从堆栈中弹出。因此,没有 ABA 问题,也没有标记指针。足以证明我遇到的比赛:

#include <atomic>
#include <list>
#include <thread>
#include <type_traits>

struct Node {
  Node() = default;
  Node(Node *n) { next.store(n); }
  std::atomic<Node *> next;
};

using Memory = std::aligned_storage_t<sizeof(Node)>;

struct Stack {
  bool pop_and_use() {
    for (Node *current_head = head.load(); current_head;) {
      Node *next = current_head->next.load(); // READ RACE
      if (head.compare_exchange_weak(current_head, next, std::memory_order_seq_cst)) {
        current_head->~Node();
        Memory *mem = reinterpret_cast<Memory *>(current_head);
        new (mem) int{0}; // use memory with non-atomic write (WRITE RACE)
        return true;
      }
    }
    return false;
  } …
Run Code Online (Sandbox Code Playgroud)

c++ multithreading thread-sanitizer

6
推荐指数
1
解决办法
180
查看次数

使用嵌入式引用计数器时,ThreadSanitizer报告"操作员删除时的数据竞争(void*)"

请看下面的代码:

#include <pthread.h>
#include <boost/atomic.hpp>

class ReferenceCounted {
  public:
    ReferenceCounted() : ref_count_(1) {}

    void reserve() {
      ref_count_.fetch_add(1, boost::memory_order_relaxed);
    }

    void release() {
      if (ref_count_.fetch_sub(1, boost::memory_order_release) == 1) {
        boost::atomic_thread_fence(boost::memory_order_acquire);
        delete this;
      }
    }

  private:
    boost::atomic<int> ref_count_;
};

void* Thread1(void* x) {
  static_cast<ReferenceCounted*>(x)->release();
  return NULL;
}

void* Thread2(void* x) {
  static_cast<ReferenceCounted*>(x)->release();
  return NULL;
}

int main() {
  ReferenceCounted* obj = new ReferenceCounted();
  obj->reserve(); // for Thread1
  obj->reserve(); // for Thread2
  obj->release(); // for the main()
  pthread_t t[2];
  pthread_create(&t[0], NULL, Thread1, obj); …
Run Code Online (Sandbox Code Playgroud)

c++ multithreading boost reference-counting thread-sanitizer

5
推荐指数
1
解决办法
927
查看次数

GCC 4.9.1 ThreadSanitizer“就像通过睡眠同步”

我正在一个大型项目中清理 ThreadSanitizer 警告。特别是在这种情况下,有一个生成的线程从文件、生产者中读取。然后有一个或多个解压线程作为线程池的一部分。最后,有一个线程实际上通过检索解压缩的块来进行处理。这当然允许同时解压缩多个块。

该项目在许多位置通过原子 bool 和 进行同步usleep(),特别包括这一处。当然,这并不理想,也是分配给我的事情之一。

但只要表示了互斥体和锁,我就看不出 ThreadSanitizer 会抱怨什么问题(除了与使用条件变量相比可能降低效率之外)。

ThreadSanitizer 抱怨数据争用“好像通过睡眠同步”,并提供了调用位置usleep()。我的问题是,当然通过睡眠同步并不理想,但只要尊重互斥体,我就不会看到数据竞争。据我了解互斥体的工作方式,我确实相信它们受到尊重。

因此,我尝试创建一组最小的重现步骤,以便准确识别 ThreadSanitizer 所抱怨的内容。

这是我想出的代码:

// g++ --std=c++11 -lpthread as-if-synchronized-via-sleep.cpp -g -fsanitize=thread -pie -fPIC
#include <iostream>
#include <iomanip>
#include <thread>
#include <vector>
#include <atomic>
#include <mutex>
#include <chrono>
#include <cstdlib>

#include <unistd.h>

class Data {
public:
        char uncompressed[1024];
        char compressed[1024];
        std::atomic<bool> done = {false};
};

int main(int argc, char **argv) {
        std::atomic<bool> done = {false};
        std::atomic<int> count = {0};

        std::mutex m;
        std::vector<Data*> v;

        std::thread provider{[&](){ …
Run Code Online (Sandbox Code Playgroud)

multithreading c++11 thread-sanitizer gcc4.9

5
推荐指数
1
解决办法
2058
查看次数

std::cout 插入运算符的线程安全

我一直认为usingstd::cout << something是线程安全的。

对于这个小例子

#include <iostream>
#include <thread>

void f()
{
   std::cout << "Hello from f\n";
}

void g()
{
   std::cout << "Hello from g\n";
}

int main()
{
   std::thread t1(f);
   std::thread t2(g);
   t1.join();
   t2.join();
}
Run Code Online (Sandbox Code Playgroud)

我的期望是两个输出的顺序是未定义的(实际上这就是我在实践中观察到的),但调用是operator<<线程安全的。

然而,ThreadSanitizer、DRD 和 Helgrind 似乎都给出了有关访问 std::__1::ios_base::width(long) 和 std::__1::basic_ios<char, std::__1::char_traits >:: 的各种错误充满()

在编译器资源管理器上我没有看到任何错误

在 FreeBSD 13 上,ThreadSanitizer 给了我 3 个警告,上面列出的两个警告加上底层 I/O 缓冲区的 malloc/memcpy。

同样在 FreeBSD 13 中,DRD 给出 4 个错误,width()两个fill()线程乘以 2 个错误。

最后,FreeBSD 13 Helgrind …

multithreading valgrind c++11 thread-sanitizer

5
推荐指数
1
解决办法
245
查看次数

TSan 种族随着 Alignas 消失(32)

我有一个无锁队列的实现,我相信它是正确的(或者至少是无数据竞争的):

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

struct Job {
  int id;
  int data;
};

class JobQueue {
  using stdmo = std::memory_order;

  struct Node {
    std::atomic<Node *> next = QUEUE_END;
    Job job;
  };

  static inline Node *const QUEUE_END = nullptr;
  static inline Node *const STACK_END = QUEUE_END + 1;

  struct GenNodePtr {
    Node *node;
    std::uintptr_t gen;
  };

  alignas(64) std::atomic<Node *> jobs_back;
  alignas(64) std::atomic<GenNodePtr> jobs_front;
  alignas(64) std::atomic<GenNodePtr> stack_top;

 public:
  JobQueue()
      : jobs_back{new Node{}},
        jobs_front{GenNodePtr{jobs_back.load(stdmo::relaxed), 1}},
        stack_top{GenNodePtr{STACK_END, 1}} {}

  ~JobQueue() …
Run Code Online (Sandbox Code Playgroud)

c++ lock-free thread-sanitizer

5
推荐指数
0
解决办法
93
查看次数

C++ 如何通过变量的地址获取变量

上下文:我正在为我的程序使用线程清理程序,它显示我的程序存在数据争用。我 100% 确定为什么(也许有太多内存访问),线程清理程序不会给出无效访问的确切堆栈跟踪。只有

Previous read of size 4 at 0x7b1800004140 by thread T36:
    [failed to restore the stack]
Run Code Online (Sandbox Code Playgroud)

我尝试history_size=7根据文档设置运行线程清理程序时,但仍然无法获取堆栈跟踪。

我知道C/C++出于安全考虑支持地址随机化,所以我用它-fno-stack-protector来编译我的程序,这使得多次运行时无效地址访问相同。

我想知道如何获取该地址上驻留的变量,以便我可以直接获取我非法访问它的位置?

我使用 bazel 作为我的构建系统,它间接依赖于 clang v13.0.0。

c++ memory-address thread-sanitizer

5
推荐指数
0
解决办法
136
查看次数