我们可以使用GDB和Valgrind对ROS程序进行调试,关键就是roslaunch中的launch-prefix
参数,但是这两个工具不能同时在roslaunch中使用
GDB
可以在使用catkin_make
时,添加编译类型为Debug:catkin_make -DCMAKE_BUILD_TYPE=Debug --pkg pub
,另一种方法是在CMakeLists中添加下列信息,这同CMake是一样的:1
2
3SET(CMAKE_BUILD_TYPE "Debug")
SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb")
SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall")
编译后,运行命令要加--prefix
参数,格式如下1
rosrun --prefix 'gdb -ex run --args' [package_name] [node_name]
然后会进入GDB环境运行节点。
运行结果如下,在代码第20行有一句ROS_BREAK
:
不过更常用的是roslaunch,除了修改CMakeLists外,还需要修改launch文件,在type之后加一句:launch-prefix="xterm -e gdb --args"
,也就是添加launch-prefix
属性来启动node,但是注意不能通过SSH隧道启动GDB,也就是不能从本机SSH到远程机启动GDB,结果会报错,因为本机要弹出GDB的窗口
1 | launch-prefix="xterm -e gdb --args" #在一个单独的xterm窗口运行节点,需要手动输入run来运行 |
剩下的就是GDB的使用了
Valgrind
配置很简单,除了上面修改CMakeLists
,把launch中的参数修改如下:1
launch-prefix="valgrind --leak-check=full --show-reachable=yes --undef-value-errors=yes --track-fds=yes" #后面的参数写在同一行
使用launch文件时,不要设置respawn
为true,那样会没完没了地执行valgrind。在启动launch之后就会启动valgrind工具检测内存泄露,并执行性能分析,剩下的就是valgrind的使用了。
下面是一个简单的节点,只发布一个std_msgs
消息,用valgrind测试的结果:
检查一下这个简单的程序:1
2
3
4
5
6
7int main(int argc, char** argv)
{
ros::init(argc,argv,"node");
ros::NodeHandle nh;
ROS_INFO("------ waiting for client's request ------");
return 0;
}
结果竟然有内存泄露:
上网一查,原来真是kinetic的bug,分析在这里,是一个指针没有delete就置为NULL,有人解决之后,在melodic没有了这个bug
nemiver
nemiver是基于GNOME的gdb前端,非常强大,但是速度有点慢。配置:launch-prefix="nemiver"
在UBUNTU下直接使用apt安装: sudo apt-get install nemiver