使用Valgrind对ros工程进行debug

问题:

在ros开发过程中出现了内存问题,系统报错
malloc(): invalid size (unsorted)这种问题非常常见,但是整个项目太大,虽然保存了任务进度,复现了问题,但是依然找不到问题的原因。
代码片段。

// An highlighted block
void DynamicVoronoi::initializeEmpty(int _sizeX, int _sizeY) 
{
  sizeX = _sizeX;
  sizeY = _sizeY;
  if (data)  
  delete[] data;
  
  dataCell c;
  c.dist = INFINITY;
  c.sqdist = INT_MAX;
  c.obstX = invalidObstData;
  c.obstY = invalidObstData;
  c.voronoi = free;
  c.queueing = fwNotQueued;
  c.needsRaise = false;
  // if(sizeY==105)  data = new dataCell[10];
  // delete[] data;
  data = new dataCell[sizeX*sizeY];//问题行
  for (int x=0; x<sizeX*sizeY; x++) data[x] = c;
}

利用指令htop查看内存占用情况,发现内存5/16G,裕量不小,怀疑是其他地方的内存泄漏。

valgrind debug

ros系统中一般采用catkin_make 对工程进行编译。本工程由两个节点,一个是plane_oct,一个planner_server.
在devel/lib/planner_server文件夹下找到可执行文件,直接通过valgrind ./planner_server启动。其他节点正常采用sh文件启动。
记得planner_server包编译的时候CmakeList必须是debug模式

# SET(CMAKE_BUILD_TYPE Debug) #debug模式
SET(CMAKE_BUILD_TYPE Release) #Release

运行过程中即可得到内存相关的报错信息

==218072== Invalid write of size 1
==218072==    at 0x393739: Local_planner::Optimize_Bspline() (planner.cpp:650)
==218072==    by 0x39452B: main (planner.cpp:742)
==218072==  Address 0x2922eb69 is 0 bytes after a block of size 6,825 alloc'd
==218072==    at 0x483BE63: operator new(unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==218072==    by 0x3B1C49: __gnu_cxx::new_allocator<signed char>::allocate(unsigned long, void const*) (new_allocator.h:114)
==218072==    by 0x3AF053: std::allocator_traits<std::allocator<signed char> >::allocate(std::allocator<signed char>&, unsigned long) (alloc_traits.h:443)
==218072==    by 0x3AB555: std::_Vector_base<signed char, std::allocator<signed char> >::_M_allocate(unsigned long) (stl_vector.h:343)
==218072==    by 0x3A5757: std::vector<signed char, std::allocator<signed char> >::_M_fill_insert(__gnu_cxx::__normal_iterator<signed char*, std::vector<signed char, std::allocator<signed char> > >, unsigned long, signed char const&) (vector.tcc:561)
==218072==    by 0x39E2F2: std::vector<signed char, std::allocator<signed char> >::resize(unsigned long, signed char const&) (stl_vector.h:957)
==218072==    by 0x393673: Local_planner::Optimize_Bspline() (planner.cpp:638)
==218072==    by 0x39452B: main (planner.cpp:742)
==218072== 
==218072== Invalid write of size 1
==218072==    at 0x39375C: Local_planner::Optimize_Bspline() (planner.cpp:652)
==218072==    by 0x39452B: main (planner.cpp:742)
==218072==  Address 0x2922eb6e is 5 bytes after a block of size 6,825 alloc'd
==218072==    at 0x483BE63: operator new(unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==218072==    by 0x3B1C49: __gnu_cxx::new_allocator<signed char>::allocate(unsigned long, void const*) (new_allocator.h:114)
==218072==    by 0x3AF053: std::allocator_traits<std::allocator<signed char> >::allocate(std::allocator<signed char>&, unsigned long) (alloc_traits.h:443)
==218072==    by 0x3AB555: std::_Vector_base<signed char, std::allocator<signed char> >::_M_allocate(unsigned long) (stl_vector.h:343)
==218072==    by 0x3A5757: std::vector<signed char, std::allocator<signed char> >::_M_fill_insert(__gnu_cxx::__normal_iterator<signed char*, std::vector<signed char, std::allocator<signed char> > >, unsigned long, signed char const&) (vector.tcc:561)
==218072==    by 0x39E2F2: std::vector<signed char, std::allocator<signed char> >::resize(unsigned long, signed char const&) (stl_vector.h:957)
==218072==    by 0x393673: Local_planner::Optimize_Bspline() (planner.cpp:638)
==218072==    by 0x39452B: main (planner.cpp:742)
==218072== 
==218072== Invalid read of size 4
==218072==    at 0x393705: Local_planner::Optimize_Bspline() (planner.cpp:649)
==218072==    by 0x39452B: main (planner.cpp:742)
==218072==  Address 0x189d62e4 is 0 bytes after a block of size 35,700 alloc'd
==218072==    at 0x483BE63: operator new(unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==218072==    by 0x3B1A65: __gnu_cxx::new_allocator<float>::allocate(unsigned long, void const*) (new_allocator.h:114)
==218072==    by 0x3AED8B: std::allocator_traits<std::allocator<float> >::allocate(std::allocator<float>&, unsigned long) (alloc_traits.h:443)
==218072==    by 0x3AB135: std::_Vector_base<float, std::allocator<float> >::_M_allocate(unsigned long) (stl_vector.h:343)
==218072==    by 0x3A51FF: std::vector<float, std::allocator<float> >::_M_fill_insert(__gnu_cxx::__normal_iterator<float*, std::vector<float, std::allocator<float> > >, unsigned long, float const&) (vector.tcc:561)
==218072==    by 0x39E244: std::vector<float, std::allocator<float> >::resize(unsigned long, float const&) (stl_vector.h:957)
==218072==    by 0x392381: Local_planner::GetMapService(bool) (planner.cpp:554)
==218072==    by 0x3944F7: main (planner.cpp:738)
==218072== 
V图准备前


运行过程中即可得到内存相关的报错信息

几个invalid读写大概率就是引起上文内存分配错误的原因。

相关代码片段

                                        nav_msgs::OccupancyGrid lcpmap2d_test;
                                        lcpmap2d_test.info.height = lcpmap2d.height;
                                        lcpmap2d_test.info.width = lcpmap2d.width;
                                        lcpmap2d_test.info.resolution = lcpmap2d.resolution;
                                        lcpmap2d_test.info.origin.position.x = lcpmap2d.org_x;
                                        lcpmap2d_test.info.origin.position.y = lcpmap2d.org_y;
                                        lcpmap2d_test.data.resize(lcpmap2d.data.size(),100);

                                        int size_lcp = int(lcpmap2d_test.info.height)*int(lcpmap2d_test.info.height);
                                        float kkzs_orgx = float(lcpmap2d_test.info.origin.position.x);                                          
                                        float kkzs_orgy = float(lcpmap2d_test.info.origin.position.y);
                                        float kkzs_rs = lcpmap2d_test.info.resolution;
                                        int  kkzs_x = 0 ;
                                        int  kkzs_y = 0 ;

                                        for(int kkzs = 0;kkzs<size_lcp;kkzs++)
                                        {
                                        if(lcpmap2d.data[kkzs]<=-50)
                                          lcpmap2d_test.data[kkzs] = 100;  //invalid write
                                        else                                        
                                          lcpmap2d_test.data[kkzs] = 0;  //invalid write
                                        }

可以发现 int size_lcp = int(lcpmap2d_test.info.height)*int(lcpmap2d_test.info.height);中尺寸错误,应该是
int size_lcp = int(lcpmap2d_test.info.height)*int(lcpmap2d_test.info.width);

小结:一般这种内存错误都以较难定位,valgrind是一个很好的工具,内存的操作有非常详细的信息。对于大多数情况,vscode debug+valgrind都可以解决问题。在段错误、弃核的情况下非常好用。

链接: link
提供了valgrind的相关指南。

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Valgrind是一个用于进行程序性能分析和调试的工具,可以帮助检测ROS程序中的内存泄漏等问题。它主要有四种工具:Memcheck、Callgrind、Cachegrind和Helgrind。其中,Memcheck是用于检查内存泄漏的利器,可以通过对ROS程序进行可视化分析来查找内存泄漏问题。 在编译ROS包时,可以使用如下命令进行编译和运行Valgrind的内存泄漏检查: ``` catkin_make -DCMAKE_BUILD_TYPE=Debug roscore valgrind --tool=memcheck --leak-check=yes --log-file=valgrind.log ./devel/lib/package_foo/executable_bar ``` 这个命令会在编译ROS包时启动roscore,并使用Valgrind工具对指定的ROS可执行文件进行内存泄漏检查,并将检查结果输出到valgrind.log文件中。 如果需要下载Valgrind的源码并进行安装,可以按照以下步骤进行: 1. 下载Valgrind的源码并解压缩: ``` tar jxvf valgrind-3.14.0.tar.bz2 ``` 2. 进入解压后的Valgrind目录: ``` cd valgrind-3.14.0/ ``` 3. 执行autogen.sh脚本: ``` ./autogen.sh ``` 4. 配置安装路径: ``` ./configure --prefix=/home/pony/valgrind ``` 5. 编译Valgrind: ``` make ``` 6. 安装Valgrind: ``` make install ``` 7. 将Valgrind的bin目录添加到系统环境变量中: ``` sudo gedit ~/.bashrc export PATH=$PATH:~/valgrind/bin/ source ~/.bashrc ``` 通过以上步骤,可以下载Valgrind的源码并进行编译安装,并将Valgrind的bin目录添加到系统环境变量中,方便在终端中直接使用Valgrind命令。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [ValgrindROS程序的可视化分析](https://blog.csdn.net/lovely_yoshino/article/details/119418863)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值