调用gdb编译需要在cc后面加 -g参数再加-o;
那么可以使用下面这些命令方便地使程序一直执行到swap()的入口:
until 13
until swap
until swapflaw.c:13
until swapflaw.c:swap监视点是一种特殊类型的断点,区别在于监视点没有“住在”某一行源代码中,而是指示GDB每当某个表达式改变了值就暂停执行。
设置监视点:watch z(变量名)也可以是复杂的表达式
注意只能监视存在且在作用域内的变量。一旦变量不再存在调用栈的任何帧中,GDB会自动删除监视点。(gdb) list line1,line2
查看源代码
list lineNum 在lineNum的前后源代码显示出来
list + 列出当前行的后面代码行
list - 列出当前行的前面代码行
list function
set listsize count
设置显示代码的行数
show listsize
显示打印代码的行数
list first,last
显示从first到last的源代码行finish命令指示GDB恢复执行,直到恰好在当前帧完成之后为止。
until命令通常用来在不进一步在循环中暂停(除了循环中的中间断点)的情况下完成正在执行的循环。until会执行循环的其余部分(如果遇到断点,还是会暂停),让GDB在循环后面的第一行代码处暂停。
until命令也可以接受源代码中的位置作为参数,其用法与break命令同。printf命令和C中printf函数类似,只是括号是可选的
让GDB在每次到达某个断点时自动执行一组命令,从而自动完成某一任务。
使用commands命令设置命令列表:
commands breakpoint_number
…
commands
…
end将正常断点转变为条件断点:condition break_p_num(断点编号) cond(条件)
在有效的C条件语句中几乎可以用任何表达式。也可以用自己的函数或者库函数,只要他们被链接到程序中。
如:condition 1 num_y == 1
只有当满足条件num_y == 1时,GDB才会在断点1处暂停程序的执行。
如果以后要删除条件,但是保持断点,只需键入:cond break_p_num(断点编号)
用break if可以将break和condition命令组合成一个步骤:
break line_num(行号) if cond(条件)
例子:(gdb) nreak 30 if num_y == 1
注意,条件语句可以用括号()括起来,也可以不用。
查看栈帧:frame num(栈帧编号)
注意栈帧编号规则,当前正在执行的函数的帧被编号为0,其父帧(即该函数的调用者的栈帧)被编号为1,父帧的父帧被编号为2,以此类推。
跳到调用栈中的下一个父帧:up
引向相反方向:down显示整个栈,即当前存在的所有帧的集合:backtrace
常用命令
[root@redhat home]#gdb 调试文件:启动gdb
(gdb) l
:(字母l)从第一行开始列出源码
原文链接
(gdb) break n
:在第n行处设置断点(gdb) break func
:在函数func()的入口处设置断点(gdb) info break
: 查看断点信息(gdb) r
:运行程序(gdb) n
:单步执行(gdb) c
:继续运行(gdb) p
变量 :打印变量的值(gdb) bt
:查看函数堆栈(gdb) finish
:退出函数(gdb) shell
命令行:执行shell命令行(gdb) set args
参数:指定运行时的参数(gdb) show args
:查看设置好的参数(gdb) show paths
:查看程序运行路径;set environment varname [=value]
设置环境变量。如:set env USER=hchen;show environment [varname]
查看环境变量;(gdb) cd
相当于shell的cd;(gdb)pwd
:显示当前所在目录(gdb)info program
: 来查看程序的是否在运行,进程号,被暂停的原因。(gdb)clear 行号n
:清除第n行的断点(gdb)delete 断点号n
:删除第n个断点(gdb)disable 断点号n
:暂停第n个断点(gdb)enable 断点号n
:开启第n个断点(gdb)step:
单步调试如果有函数调用,则进入函数;与命令n不同,n是不进入调用的函数的list :简记为 l
,其作用就是列出程序的源代码,默认每次显示10行。list 行号:
将显示当前文件以“行号”为中心的前后10行代码,如:list 12list 函数名
:将显示“函数名”所在函数的源代码,如:list mainlist
:不带参数,将接着上一次 list 命令的,输出下边的内容。
注意 :如果运行list 命令得到类似如下的打印,那是因为在编译程序时没有加入 -g 选项:(gdb) list
1 ../sysdeps/i386/elf/start.S: No such file or directory.
in ../sysdeps/i386/elf/start.Srun
:简记为 r ,其作用是运行程序,当遇到断点后,程序会在断点处停止运行,等待用户输入下一步的命令。
回车:重复上一条命令。set args
:设置运行程序时的命令行参数,如:set args 33 55show args
:显示命令行参数continue
:简讯为 c ,其作用是继续运行被断点中断的程序。break
:为程序设置断点。break 行号
:在当前文件的“行号”处设置断点,如:break 33break 函数名
:在用户定义的函数“函数名”处设置断点,如:break cb_buttoninfo breakpoints
:显示当前程序的断点设置情况disable breakpoints Num
:关闭断点“Num”,使其无效,其中“Num”为 info breakpoints 中显示的对应值enable breakpoints Num
:打开断点“Num”,使其重新生效step
:简记为 s ,单步跟踪程序,当遇到函数调用时,则进入此函数体(一般只进入用户自定义函数)。next
:简记为 n,单步跟踪程序,当遇到函数调用时,也不进入此函数体;此命令同 step 的主要区别是,step 遇到用户自定义的函数,将步进到函数中去运行,而 next 则直接调用函数,不会进入到函数体内。until
:当你厌倦了在一个循环体内单步跟踪时,这个命令可以运行程序直到退出循环体。finish
: 运行程序,直到当前函数完成返回,并打印函数返回时的堆栈地址和返回值及参数值等信息。stepi或nexti
:单步跟踪一些机器指令。print 表达式
:简记为 p ,其中“表达式”可以是任何当前正在被测试程序的有效表达式,比如当前正在调试C语言的程序,那么“表达式”可以是任何C语言的有效表达式,包括数字,变量甚至是函数调用。print a:
将显示整数 a 的值print ++a:
将把 a 中的值加1,并显示出来print name
:将显示字符串 name 的值print gdb_test(22)
:将以整数22作为参数调用 gdb_test() 函数print gdb_test(a)
:将以变量 a 作为参数调用 gdb_test() 函数bt
:显示当前程序的函数调用堆栈。display 表达式
:在单步运行时将非常有用,使用display命令设置一个表达式后,它将在每次单步进行指令后,紧接着输出被设置的表达式及值。如: display awatch 表达式
:设置一个监视点,一旦被监视的“表达式”的值改变,gdb将强行终止正在被调试的程序。如: watch akill
:将强行终止当前正在调试的程序help 命令
:help 命令将显示“命令”的常用帮助信息call 函数(参数)
:调用“函数”,并传递“参数”,如:call gdb_test(55)layout
:用于分割窗口,可以一边查看代码,一边测试:layout src
:显示源代码窗口layout asm
:显示反汇编窗口layout regs
:显示源代码/反汇编和CPU寄存器窗口layout split
:显示源代码和反汇编窗口Ctrl + L
:刷新窗口quit
:简记为 q ,退出gdb
当然,gdb的功能远不止这些,包括多进程/多线程/信号/远程调试等功能在这里均没有提及,有需要的读者可以参考其它信息