。的变种 std::unique_ptr in a loop - memory leaks
在此修改后的问题中,RunSimulation()
是一种成员方法。
我希望unique_ptr
中的sim
个对象(main()
)中的一个在main()
内到期,而另一个对象(r
)在main()
内发送{ {1}} 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();
}
。如果你能提供一个有效的代码,那就太好了。
// my-dialog.js
'use es6'
export default locals => ({
locals, // will be bound to the controller instance!
template:
`
<p>Something: <span>{{$ctrl.foo}}</span></p>
<md-button ng-click="$ctrl.onSave()">Save</md-button>
<md-button ng-click="$ctrl.cancel()">Cancel</md-button>
` ,
bindToController: true,
controllerAs: '$ctrl',
controller: function($mdDialog, myService) {
// this.foo = ..will be provided in locals as an input parameter..
// this.onSave = () { ..will be provided as output parameter.. }
this.cancel = () => {
$mdDialog.cancel()
}
},
clickOutsideToClose: true
})
答案 0 :(得分:2)
您尝试将boost::bind
创建的仿函数传递给create_thread
的尝试失败,原因是我在answer中解释了您之前提问的原因。
使用lambda的尝试应该编译,但它有一个微妙的错误,将导致未定义的行为。我可能误解了你之前的回答,但这就是发布MCVE非常重要的原因。您在上一个问题中发布的小片段并未显示您打算如何使用该代码。
lambda的问题在于它只存储对unique_ptr
的引用。在执行RunSimulation
调用之前,您不会转让所有权,换句话说,只有在线程执行开始后才会进行所有权转移。但到那时for
中的main
循环可能已经转移到下一次迭代,导致上一次迭代中Result
所持的unique_ptr
被删除。取消引用unique_ptr
中的RunSimulation
会导致未定义的行为。
解决这个问题的方法是将unique_ptr
的所有权立即转移到lambda,然后让lambda在调用RunSimulation
时再次转让所有权。以下lambda表达式可以满足您的需求
[&sim, r=std::move(r)] () mutable {
sim->RunSimulation(std::move(r));
}
为了解释发生了什么,lambda通过引用(sim
)捕获&sim
并且使用C ++ 14的lambda init捕获来将r
内main
的所有权转让给作为lambda成员的r
(r=std::move(r)
)(您可以将lambda&#39;成员r
称为mutable
如果你想要别的东西)。 lambda本身必须为const
,因为您需要对r
数据成员进行非move
访问权限,以便在调用RunSimulation
时create_thread
unique_ptr
。
不幸的是,这不是问题的结束。使用上面的lambda调用boost::thread
仍然没有编译,因为根据documentation,它要求可调用对象是可复制的。你的lambda不可复制,因为它有一个thread_group
数据成员。
解决方法是创建auto t = new boost::thread([&sim, r=std::move(r)] () mutable {
sim->RunSimulation(std::move(r));
});
threads.add_thread(t);
,然后将add_thread
创建为add_thread
。
add_thread
请注意,我无法找到thread_group
所做的有关异常安全保障的任何文档。因此,如果在thread
尝试将新线程添加到Result
时发生异常,则您的RunSimulation
对象可能会泄漏。
最后,我认为您需要重新考虑您的设计。据推测,Result
对象应该保存模拟结果。如果您在模拟结束后无法访问Result
内的main
,那么Result
将main
存储在RunSimulation
中的重点是什么?
正如我在上一个回答的评论中所建议的那样,您应该在Stuff
中创建Object.constants.include? :Stuff #=> false
的容器,并将对这些容器的元素的引用传递给constant_missing
。< / p>