Jason GNSS Beginner

GDB

2021-05-03
Jason Ding

GDB,全称The GNU Project Debugger,是一个Project 调试器,可以在许多类Unix的系统上运行,并且适用于许多编程语言。官方定义如下:

GDB, the GNU Project debugger, allows you to see what is going on `inside’ another program while it executes – or what another program was doing at the moment it crashed.

GDB can do four main kinds of things (plus other things in support of these) to help you catch bugs in the act:

  • Start your program, specifying anything that might affect its behavior.
  • Make your program stop on specified conditions.
  • Examine what has happened, when your program has stopped.
  • Change things in your program, so you can experiment with correcting the effects of one bug and go on to learn about another.

本文收集整理了一些基础的gdb调试方法。


前提

程序能够被调试的前提是程序中含有调试符号信息,对于gdb调试,可以在程序编译时加上-g使得可执行程序保留调试符号信息。对于一个已经存在的可执行程序test(以下均以test为例),可以使用gdb test查看是否包含调试符号,若不包含则会提示”no debugging symbols found“。此外,编译器优化选项(O0~O4)会在编译阶段用编译器计算得到的值直接替换掉一些局部变量,以提升程序运行效率,这种情况下会给debug带来困难,所以在编译阶段可将编译器优化选项关闭。

最后,包含调试符号信息会使得程序明显变大,不利于布置到正式生产环境中,在调试完成后,可以使用strip tset移除掉程序中的调试信息,减小程序体积,提升程序执行效率。


GDB启动方式

gdb可以调试离线程序也可以调试在线程序,还可以调试挂掉的程序。根据调试目标的不同,gdb的启动方式也不同,大体上可以分为以下三种:

  1. 调试离线程序

    gdb test
    
  2. 调试在线程序

    首先获取需要调试的程序test的进程ID(PID号)

    ps -ef | grep test
    

    获取PID后,将gdb附加到该进程(注意这里的testPID是上一步获取得到的PID号)

    gdb attach testPID
    

    调试结束后detach退出,退出后在线程序继续运行

  3. 调试崩溃的程序

    有些长时间运行的程序突然崩溃,需要排查原因,但是重启程序又无法立马复现该问题,这时候可以调试崩溃产生的core文件来排查定位崩溃原因。

    linux系统默认情况下不开启程序崩溃产生core文件,可以通过在/etc/profile 文件中加入以下命令开启

    ulimit -c unlimited
    

    产生的core文件命名为core.pid,pid为test程序的pid号,开启调试的方式为:

    gdb test core.pid
    

GDB常用命令

缩写 全称 说明
b break 添加断点
r run 运行程序
c continue 让程序继续运行
n next 运行下一行
p print 打印变量或寄存器值
info info 查看断点/线程等信息
l list 显示源码
d delete 删除断点
s step 如果有调用函数,进入调用的函数内部,相当于 step into
u until 运行到指定行停下来
enable enable 启用指定断点(这里的启用和禁用在程序结束,重新运行程序的时候不会失效)
disable disable 禁用指定断点

命令行参数输入

以test程序为例,假设test有两个传入参数”name“和‘”100“,则调试的启动方法如下:

gdb test                     # 进入gdb调试
set args "name" 100          # 设定参数

使用show args可以查看当前设置的传入参数,若想要删除已经设置好的参数,直接set args不加任何参数即可。


braek命令

break 命令(简写为 b)即添加断点的命令,可以使用以下方式添加断点:

  • break functionname,在函数名为 functionname 的入口处添加一个断点;
  • break LineNo,在当前文件行号为 LineNo 处添加一个断点;
  • break filename:LineNo,在 filename 文件行号为 LineNo 处添加一个断点。

临时断点tbreak

所谓临时断点,就是一旦该断点触发一次后就会自动删除,添加断点的方法与break一样。

条件断点break if

条件断点的使用方法为break line-or-function if expr,例如:

break 46 if satsize==100

until命令

until命令缩写为u,until "行号"可以快速执行完中间的代码到指定行停止。


finish命令和return命令

实际调试到某一个函数内部的时候,不需要再一步一步next执行到函数返回处,这个时候可以使用finish命令直接执行完当前函数并返回到上一层调用的地方。return命令与finish类似,但是return会立即返回,也就是说,如果当前函数还有剩余的代码未执行完毕,也不会执行了,另外,return后面可以跟指定数值,即修改函数的返回值为指定数值。


display命令

调试程序的时候通常我们需要监视某个变量的值,display命令可以实现该功能。display 命令监视的变量或者内存地址,每次程序中断下来都会自动输出这些变量或内存的值。假设当前有一些变量,每次断点停下来我们都希望 GDB 可以自动输出这些变量的最新值,那么使用“display 变量名”设置即可。

info display 查看当前已经自动添加了哪些值, delete display 清除全部需要自动输出的变量,delete diaplay 编号 删除某个自动输出的变量。


watch命令

watch命令可以用来监视一个变量或者一段内存,当这个变量或者该内存处的值发生变化时,GDB 就会中断下来。


Comments

Content