gpt4 book ai didi

c++ - 在循环中线程化 unique_ptr

转载 作者:搜寻专家 更新时间:2023-10-31 02:17:30 24 4
gpt4 key购买 nike

的变体 std::unique_ptr in a loop - memory leaks

在这个修改过的问题中,RunSimulation()是成员方法。

我想要一个 unique_ptr sim 中的对象 ( main() )在 main() 内到期另一个对象 ( r ) 发送到外部 main()RunSimulation() 中释放.如果您能提供工作代码,那就太好了。

class Result { public: int n; };

class Simulation
{
public:
void RunSimulation(std::unique_ptr<Result> result) {result->n = 0;}
};

void main()
{
boost::thread_group threads;

std::unique_ptr<Result> r;
std::unique_ptr<Simulation> sim = std::make_unique<Simulation>();

for (int i = 0; i < 10; i++)
{
r = std::unique_ptr<Result>(new Result);

//Erroneous lines:
//threads.create_thread(boost::bind(&Simulation::RunSimulation, boost::ref(sim), std::move(r)));
//threads.create_thread([&] {sim->RunSimulation(std::move(r)); });
}

threads.join_all();
}

最佳答案

您试图传递 boost::bind 创建的仿函数至 create_thread由于我在 answer 中解释的原因而失败对于您之前的问题。

使用 lambda 的尝试应该可以编译,但它有一个微妙的错误,会导致未定义的行为。我之前的回答可能误导了您,但这就是发布 MCVE 的原因是如此重要。您在上一个问题中发布的小片段并未显示您打算如何使用代码。


lambda 的问题是它只存储对 unique_ptr 的引用.在调用 RunSimulation 之前,您不会转让所有权执行,换句话说,所有权的转移只发生在线程执行开始之后。但到那时formain 内循环可能已经进入下一次迭代,导致 Resultunique_ptr 持有在上一次迭代中被删除。取消引用 unique_ptrRunSimulation 内然后导致未定义的行为。

解决这个问题的方法是转移 unique_ptr 的所有权立即转到 lambda,然后让 lambda 在对 RunSimulation 的调用中再次转移所有权.下面的 lambda 表达式做你想做的事

[&sim, r=std::move(r)] () mutable {
sim->RunSimulation(std::move(r));
}

为了解释发生了什么,lambda 正在捕获 sim通过引用 ( &sim ) 并且它使用 C++14 的 lambda 初始化捕获来转移 r 的所有权在 main 内到 r那是 lambda 的成员 ( r=std::move(r) ) lambda 本身需要是 r因为你需要非 mutable访问 const数据成员所以你可以r打电话的时候move .

不幸的是,您的问题还没有结束。打电话RunSimulation上面的 lambda 仍然无法编译,因为根据 documentation ,它要求可调用对象是可复制的。您的 lambda 不可复制,因为它有一个 create_thread数据成员。

解决方法是创建一个 unique_ptr然后 boost::thread 它到 add_thread .

auto t = new boost::thread([&sim, r=std::move(r)] () mutable {
sim->RunSimulation(std::move(r));
});
threads.add_thread(t);

请注意,我找不到任何关于异常安全保证 thread_group 的文档使。所以有可能在 add_thread 时发生异常尝试将新线程添加到 add_thread , 你的 thread_group对象可能会泄漏。

Live demo


最后,我认为您需要重新考虑您的设计。据推测,thread对象应该保存模拟结果。有什么意义 Result将其存储在 RunSimulation 中如果您无法访问 ResultResult 内模拟结束后?

正如我在之前回答的评论中所建议的那样,您可能应该创建一个 main 的容器在Result并将对这些容器元素的引用传递给 main .

关于c++ - 在循环中线程化 unique_ptr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35641344/

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