1, 启动调试程序及命令
// 方法一
gdb test.exe
// 方法二,先进入gdb
gdb
// 使用file命令
file test.exe
// 随后使用run命令即可调试程序
2, 断点
// 运行到某行停止运行
break 行号
// 程序进入指定功能函数时停止运行
break 函数名称
// 符合if语句条件时,运行到指定位置停止运行
break 行号/函数名称 if 条件
-
完成需要的调试后,可以使用continue命令继续执行程序。由于程序设置了两个断点,因此continue会运行到第二个断点处停住,接着继续调试。
-
在使用断点时,enable命令可以恢复暂时不起作用的断点(如已经运行了第二个断点,但想反过来运行第一个断点)。
// 恢复多个断点采用行号空格隔开 enable 1 13
-
使用disable命令设置断点失效,使程序继续使用,不在此断点处停住(例如设置了两个断点,当执行到第一个断点时,使用disable使第二个断点失效,程序将不在第二个断点处停留)。
-
使用delete命令,clear命令清除断点,区别在于clear清除断点需要标明断点所在行号,delete需要标明断点的编号。采用clear清除断点时,GDB调试工具会给出提示信息,delete则不会给出提示。
3, 检查数据的功能及命令(print,display)
printf命令:
-
打印变量或表达式的值。
print 变量名/表达式
-
执行完命令会通过’$'显示出这是在调试过程中第几次使用print命令,就是显示出当前序列号。
-
" " 如果作为 p r i n t 命令的参数 , 表示给定序号的前一个序号 , " "如果作为print命令的参数,表示给定序号的前一个序号," "如果作为print命令的参数,表示给定序号的前一个序号,"$"表示给定序号的向前第二个序号
// 表示给定序号的前一个序号 print $ // 表示给定序号的向前第二个序号 print $$
如,当前给定序号是9,那么print $表示序号为8时显示的数据,print $$ 表示为7时的数据
-
print可以用于对变量赋值,并可以打印内存中从某一部分开始的一块连续空间的内容,表达形式如下:
// 变量赋初值 print vari = 7 // 打印连续空间数据 print 开始表达式@要打印的连续空间大小
display命令:
该命令用于显示表达式的值。与print不同的是,使用该命令每当程序运行到断点处,都会显示表达式的值。
如上所示,每当运行到断点处时,都可以观察到之前变量值的变化。
-
可以使用undisplay,enable display,delete display命令设置要显示的表达式暂时无效,即在下一次运行到断点时,不显示此表达式的变量值。
-
使用enable display将暂时失效的表达式恢复。
查看变量或函数的类型(whatis,ptype)
检查表达式的信息,包括表达式的值和表达式的数据类型,可以使用whatis命令和ptype命令实现,两者的区别在于whatis命令只显示数据类型,而ptype命令可以给出类型的定义(如class类)。
修改变量的值(set)
当程序中存在一个循环体,循环次数很大的时候,在调试过程中需要观测循环变量等于某一较大值时的状态时,此时就会派上用场,可以使用set命令修改这个循环变量为需要的值。这是set命令除显示数据之外的另一功能,
查看内存(x)
可以查看内存地址中的值。
x/<n/f/u> <addr>
- addr为起始地址。
- n为一个整数,表示显示内容的个数(向后显示几个地址的内容,数组)。
- f代表输出的格式:
- x: 十六进制整数格式
- d: 有符号十进制整数格式
- u: 无符号十进制整数格式
- o: 八进制整数格式
- t:二进制整数格式
- c: 字符格式
- f: 浮点数格式
- u代表从当前地址开始向后请求的字节数。默认4字节,当指定了字节长度后,会从指定内存地址开始读写指定字节,并当作一个值取出来。
- b: 字节(byte)
- h: 双字节数值
- w: 4字节数值
- g: 8字节数值
例如n,f,u,addr可以理解为从addr地址开始以f格式显示n个u数值。
使用观察窗口功能及其命令(watch)
在使用观察窗口时,需要设置监视点,用于监视某个表达式或变量,当表达式或变量的值被读或被写时让程序停住。
- watch命令 :为表达式(变量)设置一个监视点,用于监视被写的内容,一旦表达式值(或变量值)有变化,就立即停住程序。
- rwatch命令 :用于监视某个表达式(变量)被读,当表达式值(变量值)被读取时,就停住程序
- awatch命令 : 用于当表达式(变量)的值被读或被写时,停住程序。
- info watchpoints命令 : 用于列出当前所设置的所有监视点的相关信息。
检查栈信息功能及其命令
可通过命令查看栈信息,所谓栈层信息,是指栈的层编号,当前的函数名,函数参数值,函数所在文件及行号,函数执行到的语句。有以下语句:
-
backtrace: 简写为bt,用于显示当前的函数调用栈的所有信息。bt n,若n为正整数,代表只显示栈顶上n层的栈信息,若n为负整数时,表示只显示栈底下n层的栈信息。
-
frame n: 简写为f n,其中n为从0开始的整数,表示栈中的层编号,用于显示第n层栈信息,若没有n值,可用于显示当前栈层的信息。
-
up n: 向栈底方向移动n层,若没有n,则表示向栈底方向移动一层。
-
down n:表示向栈顶方向移动n层。
-
info frame:简写为info f,可用此命令显示更为详细的栈层信息(被调用函数地址,当前函数使用编程语言,函数参数地址及值…)。
-
info args:用于显示当前函数的参数名及值。
-
info locals:用于显示当前函数局部变量及值。
-
info catch:用于显示当前函数中的异常处理信息。
检查源代码功能及其命令
查看源代码的功能有如下几种,显示源代码,搜索源代码,查看源代码的所在路径以及查看源代码的内存。
-
list: 不加任何参数表示显示当前行后面的代码
-
<+> : 显示当前行号后面的代码
-
<-> : 显示当前行号前面的代码
-
< n > : 显示程序第n行周围的代码
-
: 显示函数名为function的功能函数代码
-
<first,last> : 显示从第first行到第last行之间的代码
-
<,last> :显示当前行到last行之间的代码
-
< filename:n> : 显示文件名为filename的文件的第n行的代码
-
<filename : function> : 显示文件名为filename的文件中的函数名为function的函数的代码
默认情况,list一次会显示10行。可以通过如下命令设置显示的代码行数。
-
set listsize< count> : count为行数,可设置每次显示源代码的行数
-
show listsize : 可查看当前显示源代码的行数设置
查看源代码的内存
info line可查看程序在运行时所指定的源代码的内存地址,info line后跟参数可以是行号,可以是函数名。
可以使用disassemble查看源代码当前执行时的机器码(汇编语言代码)。
改变程序的运行功能及其命令
程序运行过程中,可以根据需要在GDB中动态改变程序正常的运行顺序,可以通过跳转语句或修改变量值的方式,改变程序的运行方向。
set
减少执行的次数,直接运行到变量值为某值时的语句。
需要注意的是: 使用set改变变量值时,若在程序中有一个变量为width,恰巧使用set命令改变width变量的值时,则会出现错误提示,因为set width是GDB中的一个命令。为了避免此种情况,在使用set改变变量值时,尽量使用set var命令后面加上为width赋值的表达式。
改变变量值可以改变程序的运行顺序,通常应用在循环语句中,提前走出循环或者查看循环中变量为某值时的状态。然而,在想要从一个分支跳到另一个分支时,无法使用set改变变量值的方法可以使用set的如下命令更改跳转执行的地址,如:
set $pc=0x400531
jump
更改执行的地址,可以跳转到指定地址的代码处。
任意跳转,打乱执行的顺序,原理也是改变当前寄存器中的值。
jump <file:line> // line为文件file的行号,代表跳转到此行开始运行
jump <addr> // addr为代码所在行的地址,代表跳转到地址为addr处的语句开始执行
在使用jump命令进行随意跳转时,会忽略正常运行顺序的语句,此种方式进行调试,运行出来的结果可能会出现错误或不是正确的输出结果,因此在使用jump命令调试时要谨慎。
return
return命令用于快速返回一个函数的返回值,当调试进入一个功能函数时,若没有必要将函数中的所有语句都执行,可以使用return命令,快速跳出这个函数,并带回函数的返回值,忽略函数中还没有执行到的语句。
使用return,可以使函数返回一个指定表达式的值,
return <exp> // 将表达式的值作为函数返回值
call
用于显示表达式的值,若表达式中是函数名,那么起到的作用就是强制跳转到该函数,并显示函数的返回值。若函数无返回值(void),那么就不显示。
call <exp> // 显示表达式的值,或显示函数的返回值
print也可以实现显示表达式值的功能,同样,若表达式为函数名,则显示函数的返回值;若函数无返回值,则显示void。