for 循环期间的动态分配会造成内存泄漏吗?
Posted
技术标签:
【中文标题】for 循环期间的动态分配会造成内存泄漏吗?【英文标题】:Will dynamic allocation during a for loop create a memory leak? 【发布时间】:2014-07-02 20:21:20 【问题描述】:我在解决动态分配问题时遇到了问题...我有一个函数 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)
如何通过动态分配变量来避免可能造成内存泄漏,但仍然能够用两个指针填充一个元组?
【问题讨论】:
使用智能指针,例如 unique_ptr 或 shared_ptr 任何没有相应删除的new()
调用都会导致内存泄漏。按照@NeilKirk 的建议使用智能指针。
@NeilKirk boost::scoped_ptr<double>
怎么样,可以吗?还是会在 lambda 函数结束时解除分配
【参考方案1】:
我更愿意将其视为双精度元组(或其数组);它消除了双精度指针元组创建的所有猜测。
不要将其视为潜在的泄漏,而应从所有权的角度来考虑。当你声明一个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()); );
【讨论】:
感谢您的回复,是的,由于各种原因,我不能只使用<double,double>
(尽管我希望我可以使用)。该文件具体只是一个基准,所以我想让指针保持活动状态直到测试结束(一点也不长)。我试图做一些类似于你的vector
但使用atomic<double>
,但c++11 不支持+=
原子双精度运算符,我被击退了。
@SyntacticFructose 如果你的程序的生命周期没有明显超过你的双打的生命周期,那么泄漏不一定是不合理的。 (除非这会使您尝试使用基准测量的内容无效。)当然,要使用结果,您仍然需要一个真正的解决方案。以上是关于for 循环期间的动态分配会造成内存泄漏吗?的主要内容,如果未能解决你的问题,请参考以下文章