这个线程消毒器警告中的种族在哪里
Where is the race in this thread sanitzer warning?
以下代码在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>();
foo.add(subscriber);
subscriber.reset();
}
std::this_thread::sleep_for(std::chrono::seconds(1));
}
堆栈跟踪警告:
WARNING: ThreadSanitizer: data race (pid=11176)
Write of size 8 at 0x7b0800000368 by thread T1 (mutexes: write M16):
#0 operator delete(void*) <null>:1062032 (libclang_rt.tsan_osx_dynamic.dylib:x86_64h+0x4f225)
#1 std::__1::__shared_ptr_emplace<float, std::__1::allocator<float> >::__on_zero_shared_weak() new:272 (minimal:x86_64+0x1000113de)
#2 std::__1::weak_ptr<float>::~weak_ptr() memory:5148 (minimal:x86_64+0x100010762)
#3 std::__1::weak_ptr<float>::~weak_ptr() memory:5146 (minimal:x86_64+0x100002448)
#4 Foo::Foo()::'lambda'()::operator()() const minimal_race.cpp:15 (minimal:x86_64+0x10000576e)
#5 void std::__1::__async_func<Foo::Foo()::'lambda'()>::__execute<>(std::__1::__tuple_indices<>) type_traits:4345 (minimal:x86_64+0x1000052f0)
#6 std::__1::__async_func<Foo::Foo()::'lambda'()>::operator()() future:2323 (minimal:x86_64+0x100005268)
#7 std::__1::__async_assoc_state<void, std::__1::__async_func<Foo::Foo()::'lambda'()> >::__execute() future:1040 (minimal:x86_64+0x100005119)
#8 void* std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, void (std::__1::__async_assoc_state<void, std::__1::__async_func<Foo::Foo()::'lambda'()> >::*)(), std::__1::__async_assoc_state<void, std::__1::__async_func<Foo::Foo()::'lambda'()> >*> >(void*) type_traits:4286 (minimal:x86_64+0x10000717c)
Previous atomic write of size 8 at 0x7b0800000368 by main thread:
#0 __tsan_atomic64_fetch_add <null>:1062032 (libclang_rt.tsan_osx_dynamic.dylib:x86_64h+0x24cdd)
#1 std::__1::shared_ptr<float>::~shared_ptr() memory:3472 (minimal:x86_64+0x1000114d4)
#2 std::__1::shared_ptr<float>::~shared_ptr() memory:4502 (minimal:x86_64+0x100002488)
#3 main memory:4639 (minimal:x86_64+0x10000210b)
SUMMARY: ThreadSanitizer: data race new:272 in std::__1::__shared_ptr_emplace<float, std::__1::allocator<float> >::__on_zero_shared_weak()
编辑:我用编译
clang++ -std=c++17 -g -fsanitize=thread -o test minimal_race.cpp
clang版本:
$ clang++ --version
clang version 7.1.0 (tags/RELEASE_710/final)
Target: x86_64-apple-darwin18.7.0
Thread model: posix
InstalledDir: /usr/local/opt/llvm@7/bin
我正在使用macOS 10.14.6
我认为这可能是libc++和clang在其weak_ptr/shared_ptr实现中的一个错误。。。
将weakptr队列更改为sharedptr队列可以修复问题,即使是旧的clang版本也是如此。
更改为第25行:
void add(const std::shared_ptr<float> subscriber) {
第33行:
std::queue<std::shared_ptr<float>> requests;
并将第42行的while重写为:
while (--numIterations) {
auto subscriber = std::make_shared<float>();
foo.add(move(subscriber));
}
相关文章:
- C++我需要了解在哪里使用指针和双指针
- 未定义的引用在哪里
- 谷歌测试中的期望值存储在哪里
- 尽管遵循了规则,内存泄漏在哪里
- 静态数据成员模板专用化的实例化点在哪里
- 在哪里放置我的函数?进入我的母语 Gui 还是进入我的演示者?
- 在哪里声明结构运算符重载
- C++ 中的自定义异常:在哪里定义它们?
- 常量参数存储在哪里 (C++)?
- 如何在 c++ 中确定一条指令(以字节为单位)在哪里结束,另一条指令从哪里开始?
- 此递归函数的每次迭代的值存储在哪里?
- 如何告诉本机节点模块所需的dll存储在哪里?
- 在哪里存储跨平台C++应用存储?
- C++泛型类错误,问题出在哪里?
- 在标准中,模板参数的语法在哪里定义,例如,'std::function<int(char)>'?
- 将类作为主要参数的语法在哪里需要?
- 模板参数在 C++ 中存储在哪里?
- 这个线程消毒器警告中的种族在哪里
- 在哪里放置#prama warning预处理器指令来抑制警告
- <在哪里转换?>警告 C4244:'initializing':从 '__int64' 转换为"int",可能会丢失数据