前言
之前培训开发的时候,一直使用IDE自带调试工具,最近涉及到Linux下的调试,因此学习一下GDB调试,希望可以加快调试速度。
GDB
概述
UNIX及UNIX-like下的调试工具。虽然它是命令行模式的调试工具,但是它的功能强大到你无法想象,能够让用户在程序运行时观察程序的内部结构和内存的使用情况。
一般来说,GDB主要帮助你完成下面四个方面的功能:
按照自定义的方式启动运行需要调试的程序。
可以使用指定位置和条件表达式的方式来设置断点。
程序暂停时的值的监视。
动态改变程序的执行环境。
正常情况下,我们可以通过help来打开帮助文档,熟悉里面的gdb选项,以下有几种GDB常用调试命令,方便以后查阅:
判断exe文件是否带有调试信息
要调试C/C++的程序,首先在编译时,要使用gdb调试程序,在使用gcc编译源代码时必须加上“-g”参数。保留调试信息,否则不能使用GDB进行调试。
若是无法提前得知exe文件是否带有调试信息,还可以利用以下命令来判断:
gdb exe文件名
试例图
如图可看到,最后会有 Reading symbols from protocol…done.
这代表exe文件带有调试信息。
如图,显而易见,这是没带有调试信息的。
另外呢,还可以使用:readelf -S exe文件名 | grep debug 来判断:
GDB调试(重头戏)
part _ 1 (加载运行)
启动GDB —— gdb
加载程序 —— file exe文件名
执行程序 —— r (未设置断点)
执行带参数程序 —— r 参数(未设置断点)
【注:】若是运行正常,则没有错误;若是运行中断,则要参见下面的core dump,打开核心转储,用gdb调试core文件。
part _ 2 (core dump)
part _ 3 (断点设置、查看源码)
行断点:【break 文件名 :行号 】
断点设置在该行开始处,注意:该行代码未被执行。
函数断点:【break 函数名】
断点设置在该函数的开始处,注意:断点所在行未被执行
条件断点
如果按上面的方法设置断点后,每次执行到断点位置都会暂停,为了避免每次都暂停,条件断点产生了。
【break test.c:6 if num > 0】’
查看断点:【info breakpoint】
可以使用info breakpoints查看断点的情况。包含设置了哪些断点,断点被命中的次数等信息。
删除断点:【delete 断点编号】
查看源代码的子命令是list,缩写形式为l
指定行号查看代码:【list first,last】
列出指定文件的源码:【list 文件名加行号或函数名】
part _ 4 (单步调试、设置变量)
next命令(可简写为n):用于在程序断住后,继续执行下一条语句。
step命令(可简写为s):它可以单步跟踪到函数内部。
continue命令(可简写为c)或者fg:它会继续执行程序,直到再次遇到断点处。
skip命令 :跳过执行
根据上面的信息可以看到,使用skip之后,将不会进入judge_sd函数。好处就是skip可以在step时跳过一些不想关注的函数或者某个文件。如果想删除skip,使用skip delete [num] 。
查看变量的值:【print 变量名】
当然,多个函数或者多个文件会有同一个变量名,这个时候可以在前面加上文件名或者函数名来区分:
p 'testfile.c'::i
p 'sum'::i
查看指针的值:【print 指针】
仅仅使用只能打印第一个值,如果要打印多个值,后面跟上@并加上要打印的长度,或者@后面跟上变量值,如下:
【注:】$可表示上一个变量,在调试链表时时经常会用到的,它有next成员代表下一个节点,则可使用下面方式不断打印链表内容,举例:
p *linkNode // 这里显示linkNode节点内容
p *$.next // 这里显示linkNode节点下一个节点的内容
part _ 5 (设置观察点)
设置观察点的作用就是:当被观察的变量发生变化后,程序就会暂停执行,并把变量的原值(Old)和新值(New)都会显示出来。设置观察点的命令是watch。
watch num