- 终于有机会总结gdb了
- 打开寄存器窗口
- 首先声明一点吧,这是我一直以来的没有搞明白的地方。
- 下面的这个程序我还弄不明白,继续debug
- list命令
- p命令
- run
- break
- 单步执行 next和step
- finish
- watch
- 查看函数体内的变量值
- assemble
- gdb查看内存指令–x
- 使用案例
终于有机会总结gdb了
打开寄存器窗口
显示的窗口如下:
如果想查看浮点寄存器,可以使用“tui reg float”命令
首先声明一点吧,这是我一直以来的没有搞明白的地方。
在这段代码中,我设置了一个断点并且运行起来,注意,断点处,21,这个21的n=1还没有被执行,只是下一次将要执行的语句,例证就是22的代码,你看,在22处, 虽然打印了n++,但是你打印 p n
, 则还是n,说明n没有加1,所以这就是下一条语句要执行的过程。
下面的这个程序我还弄不明白,继续debug
list命令
list num
显示源代码的num行的周围几行。
list function
显示函数。
p命令
打印结构体元素
使用这个命令,还可以查看结构体的各元素值
p *pstDate
打印数组元素
如果你想查看一个数组的各个元素,别像我似的傻乎乎的一个个 p a[i],节省生命的做 法应该是:
p ArrayVal@itemnum
什么意思?意思就是打印数组ArrayVal的前itemnum个元素。
格式控制
查看内存变量
x
我也不知道这一个有什么作用现在为止
查看局部变量
info local
run
set args num1 num2 num3 ..
使用show args查看设置的参数。
break
break function
你可以在一个函数前面加上b,到时候就可以在这个函数设置断点了。
break lines
break filename:linenum
在源文件filename的linenum行设置断点
break filename:function
在源文件的filename的function设置断点
break *address
在程序运行的内存空间地址处停住.
break
没有参数时,表示在下一条指令处停住。
break if
比如,设置
break if i = 10;
就是在循环体内当i等于10的时候停住。
方便一点的话,可以使用
filename:line_numbers if i == 5
比如, 我想在文件gdb.c的循环体for内当I等于5的停下来,则:
单步执行 next和step
在调用函数的那行,设置个断点,然后step就进入函数体内。
扩展的用法是next
finish
运行程序直到当前函数完成返回,并打印函数的返回时的堆栈地址、返回值及参数值。
until
使用until退出循环体。这一条十分重要哈^_^.
stepi(si) 和nexti(ni)
stepi用于单步跟踪一条机器指令,另外使用
display/i $pc
在打印出程序代码的同时打印出机器指令。
watch
watch
rwatch
awatch
info watchpoints: 列出当前所设置的所有观察点。
查看函数体内的变量值
当我们使用 s 命令进入函数体内时,除了简单的 p 打印,还要更加丰富些,比如,使用backtrace(bt)
从这里可以看出add_range()函数是main函数调用的,main传进来的参数是low=1,high=10,main的帧为1,add_range()的帧为0,使用i(info)来看函数局部变量的值。
如果想查看main函数的当前局部变量也可以,先使用frame(f)命令,选择1号栈再查看局部变量的值:
assemble
disassembles /rm
这个函数就会显示当前函数的汇编信息,其中,/r
是十六进制(raw instructions), /m
,如果你对intel 的汇编语法感兴趣,可以使用这个命令。
x/i $pc
这条命令是AT&T的语法格式的。
下面是一个简单的Hello.c的反汇编,
请仔细看这段代码,这是riscv64的反汇编:)
gdb查看内存指令–x
使用案例
一次性查看结构体各个成员的值
比如,我有一个结构体结构是这样的:
先定义一个graph,在完成一次loop操作后,这时我想查看其中的各个域的值,可以一次一次的使用:
p graph@v
等进行查看,不过这样查看效率可是不高,所以在gdb中,需要使用脚本: