赞
踩
通过调试程序,我们可以监控程序执行的每一个细节,包括变量的值、函数的调用过程、内存中数据、线程的调度等,从而发现隐藏的错误或者低效的代码
1、程序启动时,可以按照我们自定义的要求运行程序,例如设置参数和环境变量;
2、可使被调试程序在指定代码处暂停运行,并查看当前程序的运行状态(例如当前变量的值,函数的执行结果等),即支持断点调试;
3、程序执行过程中,可以改变某个变量的值,还可以改变代码的执行顺序,从而尝试修改程序中出现的逻辑错误。
yum -y install gdb
在编译时需要使用 gcc/g++ -g 选项编译源文件
调试命令 (缩写) | 作用 |
---|---|
(gdb) break (b) | 在源代码指定的某一行设置断点,其中xxx用于指定具体打断点位置 |
(gdb) run (r) | 执行被调试的程序,其会自动在第一个断点处暂停执行。 |
(gdb) continue (c) | 当程序在某一断点处停止后,用该指令可以继续执行,直至遇到断点或者程序结束。 |
(gdb) next (n) | 令程序一行代码一行代码的执行 |
(gdb) step(s) | 如果有调用函数,进入调用的函数内部;否则,和 next 命令的功能一样。 |
(gdb) until (u) | location 当你厌倦了在一个循环体内单步跟踪时,单纯使用 until 命令,可以运行程序直到退出循环体。 |
until n | n 为某一行代码的行号,该命令会使程序运行至第 n 行代码处停止 |
(gdb) print (p) | 打印指定变量的值,其中 xxx 指的就是某一变量名。 |
(gdb) list (l) | 显示源程序代码的内容,包括各行代码所在的行号。 |
(gdb) finish(fi) | 结束当前正在执行的函数,并在跳出函数后暂停程序的执行。 |
(gdb) return(return) | 结束当前调用函数并返回指定值,到上一层函数调用处停止程序执行。 |
(gdb) jump(j) | 使程序从当前要执行的代码处,直接跳转到指定位置处继续执行后续的代码。 |
(gdb) quit (q) | 终止调试。 |
1、(gdb) break location // b location
2、(gdb) break ... if cond // b .. if cond
location的值 | 含义 |
---|---|
linenum | linenum 是一个整数,表示要打断点处代码的行号。要知道,程序中各行代码都有对应的行号,可通过执行 l(小写的 L)命令看到。 |
filename:linenum | filename 表示源程序文件名;linenum 为整数,表示具体行数。整体的意思是在指令文件 filename 中的第 linenum 行打断点。 |
+ offset - offset | offset offset 为整数(假设值为 2),+offset 表示以当前程序暂停位置(例如第 4 行)为准,向后数 offset 行处(第 6 行)打断点;-offset 表示以当前程序暂停位置为准,向前数 offset 行处(第 2 行)打断点 |
function | function 表示程序中包含的函数的函数名,即 break 命令会在该函数内部的开头位置打断点,程序会执行到该函数第一行代码处暂停。 |
filename:function | filename 表示远程文件名;function 表示程序中函数的函数名。整体的意思是在指定文件 filename 中 function 函数的开头位置打断点。 |
(gdb) clear location
参数location 通常为某一行代码的行号或者某个具体的函数名。当 location 参数为某个函数的函数名时,表示删除位于该函数入口处的所有断点。
delete [breakpoints] [num]
breakpoints 参数可有可无,num 参数为指定断点的编号,其可以是delete 删除某一个断点,而非全部
enable [breakpoints] [num...] 激活用 num... 参数指定的多个断点,如果不设定 num...,表示激活所有禁用的断点
enable [breakpoints] once num… 临时激活以 num... 为编号的多个断点,但断点只能使用 1 次,之后会自动回到禁用状态
enable [breakpoints] count num... 临时激活以 num... 为编号的多个断点,断点可以使用 count 次,之后进入禁用状态
enable [breakpoints] delete num… 激活 num.. 为编号的多个断点,但断点只能使用 1 次,之后会被永久删除。
其中,breakpoints 参数可有可无;num…表示可以提供多个断点的编号,enable命令可以同时激活多个断点。
(gdb) watch cond
1、rwatch 命令:只要程序中出现读取目标变量(表达式)的值的操作,程序就会停止运行;
2、awatch 命令:只要程序中出现读取目标变量(表达式)的值或者改变值的操作,程序就会停止运行。
(gdb) print num
(gdb) p num
(gdb) print file::variable
(gdb) print function::variable
其中 file用于指定具体的文件名,funciton 用于指定具体所在函数的函数名,variable表示要查看的目标变量或表达式。
另外,print也可以打印出类或者结构体变量的值。
(gdb) display expr
(gdb) display/fmt expr
注意,display 命令和 /fmt 之间不要留有空格。以 /x 为例,应写为 (gdb)display/x expr。
(gdb) next count //不进入函数内部```
- step命令
```bash
(gdb) step count //进入函数内部```
1、(gdb) until
2、(gdb) until location
不带参数的 until命令,可以使 GDB调试器快速运行完当前的循环体,并运行至循环体外停止。
注意,until 命令并非任何情况下都会发挥这个作用,只有当执行至循环体尾部(最后一行代码)时,
until命令才会发生此作用;反之,until命令和 next 命令的功能一样,只是单步执行程序。
(gdb) jump location //直接跳到指定行继续执行程序
//如果 jump跳转到的位置后续没有断点,那么 GDB会直接执行自跳转处开始的后续代码
search <regexp> //从当前行的开始向前搜索
reverse-search <regexp> //从当前行的开始向后搜索
(gdb) backtrace [-full] [n]
n:一个整数值,当为正整数时,表示打印最里层的 n 个栈帧的信息;n为负整数时,那么表示打印最外层n个栈帧的信息;
-full:打印栈帧信息的同时,打印出局部变量的值
注意,当调试多线程程序时,该命令仅用于打印当前线程中所有栈帧的信息。
如果想要打印所有线程的栈帧信息,应执行thread apply all backtrace命令
(gdb) frame spec
1、通过栈帧的编号指定。0 为当前被调用函数对应的栈帧号,最大编号的栈帧对应的函数通常就是 main() 主函数;
2、借助栈帧的地址指定。栈帧地址可以通过 info frame 命令(后续会讲)打印出的信息中看到;
3、通过函数的函数名指定。注意,如果是类似递归函数,其对应多个栈帧的话,通过此方法指定的是编号最小的那个栈帧
(gdb) up n
n为整数,默认值为 1。该命令表示在当前栈帧编号(假设为 m)的基础上,选定 m+n为编号的栈帧作为新的当前栈帧
(gdb) down n
该命令表示在当前栈帧编号(假设为 m)的基础上,选定 m-n为编号的栈帧作为新的当前栈帧
2、查看当前栈帧中存储的信息
(gdb) info frame
该命令会依次打印出当前栈帧的如下信息:
1、当前栈帧的编号,以及栈帧的地址;
2、当前栈帧对应函数的存储地址,以及该函数被调用时的代码存储的地址
3、当前函数的调用者,对应的栈帧的地址;
4、编写此栈帧所用的编程语言;
5、函数参数的存储地址以及值;
6、函数中局部变量的存储地址;
7、栈帧中存储的寄存器变量,例如指令寄存器(64位环境中用 rip 表示,32为环境中用eip 表示)、
堆栈基指针寄存器(64位环境用 rbp表示,32位环境用 ebp表示)等
3、info args
查看当前函数各个参数的值
4、info locals
查看当前函数中各局部变量的值
如果调试正在执行中的程序,首先需要找到正在运行程序的进程号PID,之后可以用下面三个命令进行调试,进入正常的调试流程
1) gdb attach PID
2) gdb 文件名 PID
3) gdb -p PID
注意,当调试完成后,如果想令当前程序进行执行,消除调试操作对它的影响,需手动将 GDB 调试器与程序分离,分离过程分为 2 步:
执行 detach 指令,使GDB调试器和程序分离;
执行 quit(或q)指令,退出GDB调试
$ gdb test /home/homework/coresave/core.test1.7791.1615620408 -q
Reading symbols from /home/zhudi/project/linux/blog/gdb/test...done.
warning: core file may not match specified executable file.
[New LWP 7791]
Core was generated by `./test'.
Program terminated with signal 11, Segmentation fault.
#0 0x00000000004005bd in main () at core.cpp:5
5 *a = 2;
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。