问题
项目中调用了g2o,编译没有问题,但是运行的时候报错了,报错的位置是g2o的SparseOptimizer类的析构函数里调用的clear()函数.明明上一个项目运行过程中没遇到这种g2o内部的问题,而且我上一个项目到现在,没有更改过g2o库,就很懵,不知道该怎么解决这个问题.
解决过程
-
看了clear()的源码,只是简单的关于vertices和edges的指针数组的释放,于是我猜想是不是vertice和edge对象的某些变量没有赋值而导致内存报错,为了验证猜想,尝试了创建vertice指针后后直接delete该指针是没有问题的,但是传入SparseOptimizer后再delete,就会报内存错误.
-
然后又分析了SparseOptimizer的addVertex()函数,只是一些关于std库的vector和map数据结构的创建和赋值操作,没找到问题.于是准备重新安装了最新的g2o,以及它的依赖库,
-
升级安装过程中,ceres2.1版本弃用了localParamaters.改成了Manifold,还增加了对gpu的支持,因此增加了项目代码修改的工作量.
-
改完代码,编译项目的时候出现了关于ceres找不到参数的问题(there are no arguments to ‘CHECK_EQ’ that depend on a template parameter),这个错误是因为只更新了ceres,而没有同步更新g2o造成的(因为安装g2o的时候,会把cere头文件安装到自己的外部库里,而不是调用系统的ceres头文件).但因为刚升级安装了新版ceres,并且同步更新了自己的项目代码,而且错误处没有关于g2o的字眼,就使劲找ceres的问题,把源码也分析了个遍,觉得一切都合理,没有问题.找问题无果,才想到把g2o也升级安装一下再试一下,结果问题没有了.苦笑.浪费了多少宝贵时间啊!
-
升级完库,发现最开始要解决的问题还在.于是,打开O3编译,并断点调试看能不能找到解决问题的新思路,逐个打断点调试的时候,发现在创建Vertex指针的时候,会跳转到eigen库Memery.h的Eigen::internal::aligned_malloc函数,然后,恍然大悟!绝对是eigen内存问题,但我明明记得我没有改动eigen库,升级安装g2o依赖库的时候,也没有重新编译eigen,因为它已经是比较新的版本了,结果没想到啊,重新安装了最新的eigen3.4,问题就解决了.
-
这个问题2年前遇到过,但是当时了解到高版本的eigen已经解决内存报错的问题,一开始压根就没有考虑过是eigen库的问题.
教训
- 一般开源库有问题,先考虑把有问题的库,以及相关依赖库更新一下.
- 升级更新库的过程中, 要把相关依赖的库都更新完,再编译运行,不能只更新部分,然后去分析一些其奇怪问题.
- 对于无从下手的问题,要用非优化编译O3,定位到最内核的问题.