GDB调试

非ROS程序GDB调试流程

1.编译程序前在Cmakelists.txt中添加

set(CMAKE_BUILD_TYPE Debug)

2.gdb 可执行程序

​ 如果程序需要添加参数的话

​ gdb 可执行程序 r arg1 arg2 arg3

r代表的是run

ROS程序GDB调试流程

##1.编译程序前在Cmakelists.txt中添加

set(CMAKE_BUILD_TYPE Debug)

或者使用catkin_make编译的时候添加catkin_make -DCMAKE_BUILD_TYPE=Debug

##2.开始调试

运行ros程序的两种方法:

(1)rosrun

rosrun --prefix 'gdb -ex run --args' [pakage_name] [node_name]

rosrun其实就相当于直接执行二进制文件./文件.那么我们直接找到catkin_make产生的二进制文件进行运行不就完了?每一个package产生的二进制文件存放的位置在you_catkin_workspace/devel/lib/your_package_name

cd进去上面的地址,你应该能看到你在CMakeLists.txt里通过add_executable产生的那个二进制文件的名字(就是rosNode了).在terminal中输入gdb node_name

(2)roslaunch

在launch文件的node标签中添加 launch-prefix选项

<launch>
<node pkg="test"  type="debugTest1"  name="debugTest1" output="screen"
        launch-prefix="xterm -e gdb --args"/>
launch>
  • launch-prefix="xterm -e gdb --args" : run your node in a gdb in a separate xterm window, manually type run to start it

  • launch-prefix="gdb -ex run --args" : run your node in gdb in the same xterm as your launch without having to type run to start it

  • launch-prefix="stterm -g 200x60 -e gdb -ex run --args" : run your node in gdb in a new stterm window without having to type run to start it

  • launch-prefix="valgrind" : run your node in valgrind

  • launch-prefix="xterm -e" : run your node in a separate xterm window

  • launch-prefix="nice" : nice your process to lower its CPU usage

  • launch-prefix="screen -d -m gdb --args" : useful if the node is being run on another machine; you can then ssh to that machine and do screen -D -R to see the gdb session

  • launch-prefix="xterm -e python -m pdb" : run your python node a separate xterm window in pdb for debugging; manually type run to start it

  • launch-prefix="yappi -b -f pstat -o ": run your rospy node in a multi-thread profiler such as yappi.

  • launch-prefix="/path/to/run_tmux": run your node in a new tmux window; you’ll need to create /path/to/run_tmux with the contents:

    #!/bin/sh
    tmux new-window "gdb --args $*"
    

捕获Core dumps

要在进程崩溃时获取core dumps,请先设置核心文件大小限制。 检查限制,运行

ulimit -a

将core size 设置为无限制:

ulimit -c unlimited

如果roslaunch 工作目录$ROS_HOME$已经包含了一个目录named “core”,这个目录会阻止core dump创建

为了使core dumps 能被创建,设置成用进程ID作为默认的core filename,运行以下命令

sudo echo 1 > /proc/sys/kernel/core_uses_pid

Now core dumps will show up as $ROS_HOME/core.PID

GDB 调试命令

###运行程序

run

设置断点

break <where>

where指程序的哪一行

也可以

break 函数名

这样进入函数的时候程序会暂停

设置被包含程序的断点

一个rosnodeinclude了好多文件

例如

add_executable(main main.cpp b.cpp c.cpp)

之后使用

gdb main

进行调试,如果我们想在b.cpp中加一个断点,我们只需要在terminal中特殊指明是哪个cpp加上行数即可,比如

break b.cpp:line_number

其中line_number表示你想在b.cpp中的哪行代码添加breakpoint.

查看变量值

display/format <what>

what表示变量名

执行下一步

next

显示出错位置

gdb调试出错了,比如出现segmentation fault,通常会自动显示出错位置,输入where可以显示出更详细的内容

退出gdb

程序正在运行,按下crtl+c,在输入q退出.

程序没有运行,直接输入q退出.

常错点

iterator迭代器与erase等函数一起用的时候

目的:通过迭代器遍历vector元素,并将符合条件的vector元素删除。

错误代码:

for (vector::iterator it=vec.begin() ; it!=vec.end() ; it++) {
    if ( ... ) {
        vec.erase(it);
    }
}
  • 错误原因:vector.erase(iterator);删除之后,迭代器的指向不变,但是被删除元素之后的元素会前移一位,迭代器此时指向被删除元素后一个元素。如果迭代器加一,会跳过后一元素,指向再后一元素,有可能超出vector范围,造成Core dump!

正确代码:

for (vector::iterator it=vec.begin() ; it!=vec.end() ; ) {
    if ( ... ) {
        vec.erase(it);
    } else {
        it++;
    }
}

你可能感兴趣的:(Linux开发,计算机,运维,c++,c语言)