GDB调试
运行命令
run
:运行程序,当遇到断点后,程序会在断点处停止运行,等待用户输入下一步的命令;start
:执行程序至main()
主函数的起始位置,即在main()
函数的第一行语句处停止执行(该行代码尚未执行);continue
:继续执行,到下一个断点处(或运行结束);next
:单步跟踪程序,当遇到函数调用时,也不进入函数体;此命令同step
的主要区别是,step
遇到用户自定义的函数,将进入到函数中运行,而next
则直接调用函数,不会进入到函数体内;step
:单步调试如果有函数调用,则进入函数;与命令next
不同,next
不进入调用的函数;until
:可以运行程序直到退出循环体;until + 行号
:运行至某行,不仅仅用来跳出循环;finish
:运行程序,直到当前函数完成返回,并打印函数返回时的堆栈地址和返回值及参数值等信息;call
函数:调用程序中可见的函数,并传递参数,如:call gdb_test(55)
;
使用start
指令启动程序,完全等价于先在main()
主函数起始位置设置一个断点,然后再使用run
指令启动程序。
设置断点
break n
:在第n行处设置断点;break func
:在函数func()
的入口处设置断点,如break cb_button
;delete 断点号n
:删除第n个断点;disable 断点号
:暂停第n个断点;enable 断点号
:开启第n个断点;clear 行号n
:清除第n行的断点;info break
:显示当前程序的断点设置情况;delete breakpoints
:清除所有断点;
查看源码
list
:列出程序的源代码;list
行号:将显示当前文件以"行号"为中心的前后10行代码;list
函数名:将显示函数名所在函数的源代码;
打印表达式
print 表达式
:表达式可以是任何C语言的有效表达式,包括数字,变量甚至是函数调用;print a
:将显示整数a的值;print name
:将显示字符串name的值;info function
:查询函数;display 表达式
:在单步运行时将非常有用,使用display
命令设置一个表达式后,它将在每次单步进行指令后,紧接着输出被设置的表达式和值;watch 表达式
:设置一个监视点,一旦被监视的“表达式”的值改变,gdb将强行终止正在被调试的程序;
查看运行信息
where
:当前运行的堆栈列表;backtrace
:显示当前调用堆栈;info program
:查看程序是否在运行,进程号,被暂停的原因;
调试正在运行的程序
GDB对当前正在运行的进程进行调试,GDB允许开发人员中断程序并查看其状态,之后还能让这个程序正常的继续执行。
调试已经运行的进程有两种方法:
- GDB启动时,指定进程的ID,
gdb program processID
; - 使用
attach
命令和指定的进程号gdb attach processID
;
如果不想继续调试了,使用detach
命令脱离进程;
使用gdb调试Core文件
- 首先,使用
gcc
编译源文件,加上-g
以增加调试信息; - 按照上面打开
core dump
使程序异常终止时能生成core
文件; - 运行程序,使用命令
gdb program core
来查看core
文件,其中program
为可执行程序名,core
为生成的core
文件名。
GDB在调试的过程中,可以使用generate-core-file
命令来产生core dump
文件,也可以使用gcore
命令产生core dump
文件。
GDB调试多进程程序
-
使用GDB调试器的选项
follow-fork-mode
,允许选择程序在执行fork
系统调用后是继续调试父进程还是子进程;用法如下-
(gdb) set follow-fork-mode mode
-
其中
mode
的可选值为parent
和child
,分别表示调试父进程和子进程。
-
-
单独调试子进程:如果要调试进程池中的某一个子进程,则可以找到目标子进程的PID,再将其附加到GDB调试器上;
GDB调试多线程程序
info threads
:显示当前可调试的所有线程,GDB会为每个线程分配一个ID,可以使用这个ID来操作对应的线程,ID前面有“*”号的线程是当前被调试的线程;thread ID
,调试目标ID指定的线程;set scheduler-locking [off|on|step]
,调试多线程程序时,默认除了被调试的线程在执行外,其他线程也在继续执行,但有的时候我们希望只让被调试的线程运行,该命令设置scheduler-locking
的值,off
表示不锁定任何线程,即所有线程都可以继续执行,on
表示只有当前被调试的线程会继续执行;step
表示在单步执行的时候,只有当前线程会执行;