
- 编译
- 运行&退出
- 常用命令详解
- 断点命令
- 观察点命令
- 多线程相关命令
- 操作变量内存相关命令
- 栈相关命令
- 多进程相关命令
- 其他调试命令
- 其他信息
编译
调试信息
要想用gdb编译,必须用编译参数 -g 和 -ggdb 让 gcc 生成调试信息:
-g:该选项可以利用操作系统的原生格式(native format)生成调试信息,GDB 可以直接利用这个信息,其它调试器也可以使用这个调试信息;
-ggdb:为GDB 生成专用的更为丰富的调试信息,但是此时就不能用其他的调试器来进行调试了。
gcc优化
gcc提供了大量优化等级,用来对编译时间、目标文件大小、执行效率三个维度进行不同的取舍和平衡。
命令 |
说明 |
-O0 |
最少的优化(默认的编译选项),可以最大程度上配合产生代码调试信息,可以在任何代码行打断点 |
-O 或 -O1 |
有限优化,编译时占用稍微多的时间和相当大的内存,减少代码生成尺寸、缩短执行时间,去除无用的 inline 和无用的 static 函数、死代码消除等,在影响到调试信息的地方均不进行优化,在适当的代码体积和充分的调试之间平衡,代码编写阶段最常用的优化等级 |
-O2 |
高度优化,在 -O1 的基础上,采用几乎所有的目标配置支持的优化算法,用以提高目标代码的运行速度,但会牺牲部分编译速度,调试信息不友好,有可能会修改代码和函数调用执行流程 |
-O3 |
最大程度优化,在 -O2 的基础上,采取很多向量化算法,提高代码的并行执行程度,利用现代CPU中的流水线,Cache等,目标:拼命提高运行速度,那怕增加目标代码的大小 |
-Os |
相当于 -O2.5,在-O2的基础之上,尽量的降低目标代码的大小 |
编译总结
要想编译出调试用的可自行文件,编译时必需要调试参数 -g 或-ggdb;优化最好只用-O0,或-O1,再之上的就很不利于调试了,无足够的编译信息,由于优化代码的执行顺序也变了。
运行&退出
运行启动gdb的方式有:
(1) gdb program program为要执行的二进制文件;
进入gdb后,运行命令:set args [args] 添加运行参数,在用命令run直接运行程序;
(2) gdb pid pid为正在运行程序的进程id,gdb将attach到正在运行的程序;
或者先运行gdb:gdb, 再用命令 attach pid 进行调试。
(3) gdb program core 通过core文件查看调试程序;
通过方式(1)进入gdb后,可以通过 set args 指定程序运行的参数,show args 查看当前运行命令参数。
gdb退出
在命令行键入:quit,然后回车。
常用命令详解
断点命令
命令 |
说明 |
break function |
在指定函数的进入点设置中断点, c++可以用class::function或function(type,type)格式来指定函数名 |
break filename:function |
在源文件filename中的function函数入口点设置中断点 |
break filename:linenum |
在源文件filename的linenum行处设置中断点 |
break args if cond |
cond为真时, 在 break args 设置的断点处触发中断 |
tbreak args |
只会生效一次的中断点 |
info break [n] |
查看断点 |
clear [args] |
args 为(文件名)行号或函数名,无参数表示清除所有 |
delete [args] |
args 为断点号,无参数表示删除所有 |
disable [args] |
args 为断点号,无参数表示disable所有 |
enable [args] |
args 为断点号,无参数表示enable所有 |
condition bnum expr |
修改断点号为 bnum 的停止条件为 expr |
condition bnum |
清除断点号为 bnum 的停止条件 |
ignore bnum count |
忽略断点号为 bnum 的停止条件 count 次 |
观察点命令
命令 |
说明 |
watch expr |
设置观察点,在变量或表达式expr的值有变化时,马上停住程序 |
rwatch expr |
在变量或表达式expr的值被读时,马上停住程序 |
awatch expr |
在变量或表达式expr的值被读或写时,马上停住程序 |
info watchpoints |
列出当前设置的所有观察点 |
多线程相关命令
命令 |
说明 |
info threads |
查看线程 |
threads threadNo |
进入指定的线程 |
break [args] thread threadNo |
指定某线程中的断点 |
break [args] thread threadNo if cond |
指定某线程中的条件断点 |
set scheduler-locking on/step/off |
锁定当前线程/单步锁定当前线程/解除锁定 |
show scheduler-locking |
显示当前线程锁定模式 |
操作变量内存相关命令
命令 |
说明 |
file::variable |
文件中的某个全局变量 |
function::variable |
函数中的某个局部变量 |
数组名@len |
len 要查看的长度 |
whatis value |
显示变量value的值和类型 |
ptype value |
显示变量value的类型 |
set [var] value = xx |
设置变量的值,如: set nval=54 将把54保存到nval变量中,[var] 告诉gdb 之后操作的是变量 |
print x = 4 |
修改变量x的值为4 |
examin(x)/nfu addr |
查看内存, 如: x/3uh 0x54320 表示,从内存地址 0x54320 读取内容,h 表示以双字节为一个单位,3 表示三个单位,u 表示按十六进制显示 |
栈相关命令
命令 |
说明 |
backtrace(bt) |
查看函数调用栈信息 |
frame(f) num |
查看第num层栈信息 |
info args |
打印当前函数的参数名及值 |
info locals |
打印当前函数的所有局部变量及值 |
多进程相关命令
命令 |
说明 |
set follow-fork-mode parent/child |
调试父进程/子进程 |
show follow-fork-mode |
查看当前调试的fork的模式 |
detach-on-fork on/off |
只调试父进程或子进程其中一个,需要根据follow-fork-mode决定/父子进程都在gdb的控制之下,其中一个进程正常调试,需要根据follow-fork-mode决定,另一个进程会被设置为暂停状态 |
info inferiors |
显示GDB调试的所有inferior(每一个被调试程序的执行状态记录在一个名为inferior的结构中,一般情况下一个inferior对应一个进程),GDB会为他们分配ID,其中带有*的进程是正在调试的inferior |
set schedule-multiple on/off |
只有当前inferior会执行/全部是执行状态的inferior都会执行 |
set follow-exec-mode new/same |
在执行exec的inferior上控制子进程/新建一个inferior给执行起来的子进程,而父进程的inferior仍然保留 |
show follow-exec-mode |
查看follow-exec-mode设置的模式 |
set print inferior-events on/off |
打开/关闭inferior状态的提示信息 |
show print inferior-events |
查看print inferior-events设置的状态 |
其他调试命令
命令 |
说明 |
run |
运行你的程序 |
quit |
退出gdb |
continue© |
继续执行直到下一个停止点 |
step(s) |
单步调试下一步,会进入函数 |
next(n) |
单步调试下一步,不会进入函数 |
ni/si |
下一条指令,进入函数/不进入函数 |
finish |
运行程序,直到当前函数完成返回。并打印函数返回时的堆栈地址和返回值及参数值等信息 |
until(u) |
执行一行程序,若此时程序是在 for/while/do loop 循环的最后一行,则一直执行到循环结束后的第一行程序后停止 |
set/show args |
设置/显示运行参数 |
print§ value |
打印变量value |
list |
列出产生执行文件的源代码的一部分 |
ctrl + c |
在当前位置停止执行正在执行的程序,断点在当前行 |
info line ars |
args:行号,函数名,文件名:行号,文件名:函数名; 打印出所指定的源码在运行 |
时的内存地址 |
|
disassemble |
查看代码的汇编 |
其他信息
对应的pdf文档可在我的博客免费下载,同时也提供gdb的官方手册的pdf下载。