gdb?
gdb是非常强大的UNIX及UNIX-like下的程序调试工具
gdb的使用:
- 在代码编译的时候加上-g选项
- 在命令行输入gdb+文件名
调试过程
r或run:运行程序。
list/l 行号:显示文件源代码,接着上次的位置往下列,每次列10行。
list/l 函数名:列出某个函数的源代码。
s或step:进入函数调用
breaktrace(或bt):查看各级函数调⽤用及参数
info(i) locals:查看当前栈帧局部变量的值
info break :查看断点信息。
finish:执⾏行到当前函数返回,然后挺下来等待命令
print(p):打印表达式的值,通过表达式可以修改变量的值或者调⽤用函数
set var:修改变量的值
quit:退出gdb
break(b) 行号:在某一行设置断点
break 函数名:在某个函数开头设置断点
continue(或c):从当前位置开始连续而非单步执行程序
run(或r):从开始连续而非单步执行程序
delete breakpoints:删除所有断点
delete breakpoints n:删除序号为n的断点
disable breakpoints:禁用断点
enable breakpoints:启用断点
info(或i) breakpoints:参看当前设置了哪些断点
display 变量名:跟踪查看一个变量,每次停下来都显⽰示它的值
undisplay:取消对先前设置的那些变量的跟踪
until X(行号):跳至X行
n 或 next:单步执行。
p 变量:打印变量值。
多进程调试
默认情况下,gdb只会调试主进程,但是我们可以在调试之初通过两条命令来设置调试多线程
- set detach-on-fork on/off
如果参数是on,表示调试的时候要分离进程,只能调试其中一个进程;若参数为off,表示调试的时候不分离进程,进行阻塞式调试,即调试父进程时阻塞子进程,调试子进程时阻塞父进程。当然,还可以切换需要进行调试的进程。
切换调试进程:
- inferior < infer num>
查看正在调试的进程:
- info inferiors
确定调试哪个进程:
- set follow-fork-mode parent/child
如果参数是parent,表示分离或阻塞子进程,调试父进程;如果参数是child,表示分离或阻塞父进程,调试子进程。
多进程调试实例
先编写一个简单的多进程程序,接下来我们就可以开始调试了。
先看看set detach-on-fork off的情况:
fork()之后,可以查看到目前有两个正在调试的进程,默认调试父进程,但是我们可以随意切换。
再来看看set detach-on-fork on的情况:
fork()之后,只有一个正在调试的进程,因为子进程被分离出去了(这是默认情况,也可以通过设置分离父进程)。
多线程调试
1) 显示当前可调式的所有线程:
- info threads
gdb为每一个线程分配ID,这个ID后续操作的时候进行使用。
2)切换当前调试的线程为ID号线程:
- thread ID
3)让线程执行某个命令:
- thread apply ID command
只让ID号线程执行command命令
- thread apply all command
让所有线程都执行command命令
4)
- set scheduler-locking off|on|step
在使用step或者continue命令调试当前被调试线程的时候,其他线程也是同时执行的,通过这个命令就可以就可以实现这个要求,off是不锁定任何线程,也就是所有的线程都执行,这个是默认值。on是只有当前线程执行。step是在单步的时候,除了next过一个函数的情况意外,只有当前线程会执行。
多线程调试实例
先编写一个简单的多线程程序,接下来就可以开始调试啦!
查看当前可调式的所有线程,切换调试线程:
分别让单个线程和所有线程执行显示“happy”的命令: