1. Ceres
在用 Ceres 做优化时,一直都是使用以下方式构建最小二乘问题:
# INPUT_DIM (1)
# OUTPUT_DIM (3)
// 构建最小二乘问题
ceres::Problem problem;
for (int i = 0; i < N; i++) {
problem.AddResidualBlock( // 向问题中添加误差项
// 使用自动求导,模板参数:误差类型,输出维度,输入维度,维数要与前面struct中一致
new ceres::AutoDiffCostFunction<CURVE_FITTING_COST, INPUT_DIM, OUTPUT_DIM>(
new CURVE_FITTING_COST(x_data[i], y_data[i])
),
nullptr, // 核函数,这里不使用,为空
abc // 待估计参数
);
}
可以看见上面的代码段 new
了两次,这里 new
出来的是否需要释放呢?如果不手动释放,是否存在内存泄漏的风险?Ceres 文档内有对这一部分做描述:
AutoDiffCostFunction
By default AutoDiffCostFunction will take ownership of the cost functor pointer passed to it, ie. will call delete on the cost functor when the AutoDiffCostFunction itself is deleted. However, this may be undesirable in certain cases, therefore it is also possible to specify DO_NOT_TAKE_OWNERSHIP as a second argument in the constructor, while passing a pointer to a cost functor which does not need to be deleted by the AutoDiffCostFunction.
默认情况下,自动微分代价函数大致长这个样子:
CostFunction* cost_function
= new AutoDiffCostFunction<MyScalarCostFunctor, 1, 2, 2>(
new MyScalarCostFunctor(1.0)); ^ ^ ^
| | |
Dimension of residual ------+ | |
Dimension of x ----------------+ |
Dimension of y -------------------+
默认情况下,AutoDiffCostFunction
将获得传递给它的 cost functor pointer
的所有权。将在 AutoDiffCostFunction
本身被删除时对 cost functor
调用 delete
。然而,在某些情况下,这可能是不希望的,因此也可以在构造函数中指定 DO_NOT_TAKE_OWNERSHIP
作为第二个参数,同时传递一个指向 cost functor
的指针,该 cost functor
不需要被 AutoDiffCostFunction
删除。例如:
MyScalarCostFunctor functor(1.0)
CostFunction* cost_function
= new AutoDiffCostFunction<MyScalarCostFunctor, 1, 2, 2>(
&functor, DO_NOT_TAKE_OWNERSHIP);
Problem
Problem
默认接管cost_function
,loss_function
,manifold
指针的所有权。这些对象有和Problem
一样的生命周期。如果用户希望控制这些对象的销毁,可以通过在Problem::Options
结构体中设置相应的枚举来实现这一点。
注意,尽管Problem
接管了对象cost_function
和loss_function
的所有权,但它并不会妨碍用户在另一个残差块中重用它们。类似地,同一个manifold
对象可以用于多个参数块。析构函数只对每个拥有的对象调用delete
一次。
总的来说,也就是 cost_function
和 loss_function
会在 problem
析构时自动释放掉,所以并不会造成内存泄露的问题。
2. G2O
GitHub G2O
与 Ceres 内的内存管理方式异曲同工,G2O 是在将 edge
和 vertex
添加进 optimizer
时,optimizer
接管了指针的归属。optimizer
析构时自动释放 edge
和 vertex
。