【发布时间】:2015-01-01 10:58:33
【问题描述】:
在使用 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 我用来重现此警告。
【问题讨论】:
-
libc++ 不应该使用 COW 字符串,所以如果 COW 字符串是造成这种情况的原因,我会感到惊讶。
-
@BartoszKP,是的,抱歉,这是一个 COW 问题,只是我们的猜测得到了测试用例推理的支持。本质上,我们需要的是使代码线程安全,问题是有时我们会从内部收到类似的警告,例如boost::asio 所以我们并不总是能够更改代码。
-
clang 的线程清理器是一个很棒的工具,但是很难正确解释各种互斥锁和其他同步技术。可能就是这种情况 - 我从中得到了一些误报,例如,它不理解 Qt 的互斥锁。
标签: c++ multithreading c++11 thread-safety clang++