我在解决动态分配问题时遇到了一个问题…我有一个累积值的函数reduce
,在这种情况下,我正在迭代boost::tuple<double*,double*>
。我的问题在这里:
//executes this code in chunks, asynchronously
boost::tuple<double*,double*> res = hpx::parallel::reduce(hpx::parallel::par,
iter, iter+4,
boost::make_tuple<double*,double*>(g,h), [](reference a, reference b) {
double *res= new double; //dynamic allocation! I don't have anyway to delete this memory afterwards
*res = *boost::get<1>(b) * *boost::get<0>(b);
return boost::make_tuple<double*,double*>(res,res); });
函数参数为
template< typename ExPolicy, typename Iter, typename T, typename Func>
T reduce(ExPolicy execution_policy, Iter being, Iter end, T && start, Func && op)
我如何避免可能通过动态分配变量创建内存泄漏,但仍然能够用两个指针填充元组?
我宁愿将其视为双精度元组(或其数组);它消除了创建双精度指针元组的所有猜测。
与其认为这是一个潜在的泄漏,不如从所有权的角度来考虑。当你声明一个double
类型的局部变量时,栈拥有它,它将被清理。当您创建一个类型为double*
的指针时,堆栈拥有指针但不拥有该值,因此该值可能不会被清除。显然,仅仅声明一个double
是更简单和容易的,所以当这是一个选项时,更喜欢它。
现在考虑其他潜在的所有者。包含POD类型(如std::tuple<double, double>
)的元组将拥有并清除双精度类型,但包含指针类型的元组则不清楚。清理一个std::tuple<double*, double*>
不会清理双打。显然,使用双精度元组更简单、更容易,所以如果可以的话,我们更倾向于这样做。
但是,我假设出于各种原因,您必须使用双精度指针的元组
然后考虑底层数据需要的生命周期。你怎么能得到这一生?你能把双精度对象的所有权交给其他在适当的时候会被清理的东西,并把它们的地址存储在元组中指向双精度对象的非所有指针中吗?例如,让您的lambda通过引用捕获外部容器,并将您的双精度对象放入其中,并仅将其地址存储在元组中。
下面是我想表达的意思…但是要小心处理我所展示的向量。我对hpx::parallel::reduce
一无所知,但我认为它的并行特性会使这个简化版本完全不安全。两次交错调用push_back
和back
将导致创建错误的元组;对push_back
的两个重叠调用很容易损坏向量。更复杂的版本可以同步使用容器。
std::vector<double> v; // XXX: probably unsafe for parallel reduce
boost::tuple<double*,double*> res = hpx::parallel::reduce(hpx::parallel::par,
iter, iter+4,
boost::make_tuple<double*,double*>(g,h), [&v](reference a, reference b) {
v.push_back(*boost::get<1>(b) * *boost::get<0>(b));
return boost::make_tuple<double*,double*>(&v.back(), &v.back()); });