gpt4 book ai didi

c++ - 为什么线程清理器会提示这个 std::ranges::views::filter 代码?

转载 作者:行者123 更新时间:2023-12-01 14:14:56 27 4
gpt4 key购买 nike

运行此代码时线程 sanitizer complains关于数据竞赛。为什么?

#include <iostream>
#include <ranges>
#include <thread>
#include <vector>

int main(){
std::vector v{11,22,33,44,55,66};
auto view = v | std::ranges::views::filter([](const auto x){
return x>47;
});
std::jthread jt1([&]{
int sum =0;
for (const auto& val: view) {sum+=val;}
});
std::jthread jt2([&]{
int sum =0;
for (const auto& val: view) {sum+=val;}
});
}

note:这个我知道答案,最近看一个talk才知道的,但是觉得很意外,也没有现成的question,所以想分享一下。如果没有人有兴趣回答,我会自己回答。

最佳答案

[&] 在线程运行的 lambda 中应该立即发出警报。通过对线程的非const 引用传递随机对象通常是不安全的。特别是,在标准库对象上调用非 const 成员函数不是线程安全的。

begin 不是 std::ranges::filter_viewconst 成员函数。

constexpr iterator begin();
Expects: pred_.has_value().
Returns: {*this, ranges::find_if(base_, ref(*pred_))}.
Remarks: In order to provide the amortized constant time complexity required by the range concept,this function caches the result within the filter_view for use on subsequent calls.

在 libstdc++ 实现中,正是这个缓存操作触发了线程清理程序。

尝试使 view 常量导致编译错误。

reverse_view也是如此。

其他范围适配器确实有 const 重载 begin

实际上可以通过在构建线程之前调用 view.begin() 来解决这个问题。我不知道这是否会使未定义的行为正式消失(我认为它可能应该),但它确实使 sanitizer 静音。

关于c++ - 为什么线程清理器会提示这个 std::ranges::views::filter 代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63101459/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com