c++ - 在多线程环境中使用 std::string 时 Clang 的线程清理器警告

标签 c++ multithreading c++11 thread-safety clang++

在使用 clang 的线程清理器时,我们注意到数据竞争警告。我们认为这是由于 std::string 的写时复制技术不是线程安全的,但我们可能错了。我们将看到的警告减少到此代码:

void test3() {
  std::unique_ptr<std::thread> thread;

  {
    auto output = make_shared<string>();
    std::string str = "test";
    thread.reset(new std::thread([str, output]() { *output += str; }));
    // The str string now goes out of scope but due to COW
    // the captured string may not have the copy of the content yet.
  }

  thread->join();
}

在启用线程清理器的情况下编译时:

clang++ -stdlib=libc++ -std=c++11 -O0 -g -fsanitize=thread -lpthread -o test main.cpp

clang++ -std=c++11 -O0 -g -fsanitize=thread -lpthread -o test main.cpp

当多次运行时,它最终会产生这个警告:

WARNING: ThreadSanitizer: data race (pid=30829)
  Write of size 8 at 0x7d0c0000bef8 by thread T62:
    #0 operator delete(void*) <null>:0
    ...

  Previous write of size 1 at 0x7d0c0000befd by thread T5:
    #0 std::__1::char_traits<char>::assign(char&, char const&) string:639
    ...

这是线程清理程序的误报还是真正的数据竞争?如果是后者, 是否可以在不更改代码的情况下解决它(例如,通过将一些标志传递给编译器),这是字符串实现(或其他)中的已知错误吗?

更新:clang --version 输出:

Ubuntu clang version 3.5-1ubuntu1 (trunk) (based on LLVM 3.5)
Target: x86_64-pc-linux-gnu
Thread model: posix

更新:The cpp我用来重现此警告。

最佳答案

[编辑] 下面的假设被证明是错误的,请参阅评论中的链接。 T5,而不是 T62 是上面代码中产生的线程。

<罢工> 了解线程 ID 会很有用,但我假设 T5 是主线程,T62 是衍生线程。看起来拷贝是在主线程上制作的(在新线程生成之前)并在新线程上销毁(显然)。这是安全的,因为新线程在存在之前不能与主线程竞争。

因此,这是一个线程清理程序错误。未能检查上一次写入时是否存在线程 T62。

关于c++ - 在多线程环境中使用 std::string 时 Clang 的线程清理器警告,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27730158/

相关文章:

c++ - 积分的并行计算

c++ - 针对不同目标MCU开发C/C++代码的区别

c - 共享内存不适用于结构,但适用于 char*

java - 从应用程序上下文返回 ObservableList<String>

c++ - 发布获取语义以计算平均值

c++ - 从命令行构建 Visual Studio 2008 解决方案

c++ - 我怎样才能让生产者和消费者双向沟通?

c++ - 帮助,澄清我对不合格名称查找 :ISO n3290 Draft 的疑问

C++ boost::regex_match 奇怪的行为

c++ - 为什么 decimal128 可能会被标准化而 quad precision 不会?