首页 > 代码库 > gdb常用操作

gdb常用操作

2014-12-12日学习笔记

gdb调试

一、启动dgb

1、源代码编译

操作:GCC要带-g选项,目的是让编译器将符号表(对应于程序的变量和代码行的内存地址列表)保存在生成的可执行文件中。这样才能在调试会话过程中引用源代码中的变量名和行号。

举例:gcc –g –o main main.c

2、启动

启动gdb的方法有以下几种:

(1)gdb + ProgramName

说明:ProgramName 也就是可执行程序文件,一般在当前目录下

举例:gdb main

(2)gdb + ProgramName +core

说明:如果一个程序发生了错误,而且生成了core文件,core文件是程序非法执行后core dump产生的文件。一个程序必须开启core file size后才能生存core文件,用ulimite –a命令可以查看当前可执行程序的core file size。开启core file size的方法:ulimit -c unlimited。

举例:gdb main core

(3)gdb + ProgramName +PID

说明:如果程序是一个服务程序,那么可以通过制定服务程序运行时的PID,gdb会自动的attach上去。

(4) gdb -command=z x

说明:在调用GDB时可以指定启动文件,如:$gdb-command=z x

表示要在可执行文件x上运行GDB,首先要从文件z中读取命令。

gdb启动文件

有时候我们在完成调试前可能需要退出GDB,比如需要离开比较长的一段时间而且不能保持登录在计算机中。为了不丢失某些信息,可以将断点和设置的其他命令放在一个GDB启动文件中,然后每次启动GDB时会自动加载它们。

GDB启动文件默认名为.gdbinit。可以将一个文件放在主目录中用于一般用途,另一个文件放在特定项目专用的目录中。例如,可以将设置断点的命令放在后一个目录的启动文件中,在主目录的.gdbinit文件中存储开发的一些通用的宏。最好不要将编程项目放在主目录中,因为不能将项目特有的信息放在.gdbinit中。

带参数的可执行程序

如果可执行程序带有参数,可在启动gdb后,set args + 参数,就可设定程序运行时需要的参数,show paths 查看程序的运行路径。

3、以TUI模式运行GDB

在调用gdb的时候指定-tui选项或者在处于非TUI模式时在GDB中使用Ctrl+X+A组合键,可以将终端屏幕分成原文本窗口和控制台的多个子窗口

二、查看代码

list命令可用于显示指定位置处的源代码。list命令会影响当前行和当前文件。list命令有多种方式指定要显示的源代码范围,可以是行号,函数名,甚至是指令地址。常用的如下:

list linenum:显示指定行数附近的代码。

list function:显示指定函数附近的代码。

list + 列出当前行的后面代码行。

list - 列出当前行的前面代码行。

list addr:显示指定地址附近的代码。

默认情况下,GDB显示指定位置处以及其前后的10行代码,但是这是一个可设置的值。

set listsize count:设置list命令显示的源代码数量最多为count行,0表示不限制行数。

show listsize:显示listsize的值。

三、断点设置

1、设置断点

(1)break line_number在某一行设置断点。

(2)break function(函数名):在某个函数的入口(第一行可执行代码)处设置断点。

(3)break filename:function在源代码文件filename的函数function入口处处设置断点。

(4)conditionbreak_p_num(断点编号) cond(条件):将正常断点转变为条件断点

举例:condition 30  index == 5

(5)break line_num(行号) if cond(条件):用break if可以将break和condition命令组合成一个步骤:举例:(gdb) break 30 if index == 5

2、查看断点

info break:显示所有断点信息

3、删除断点:

(1)deletebreak_point_num:删除编号为break_point_num的断点;

(2)delete:删除所有断点;

(3)clear function:删除在function函数处设定的断点

(4)clearfilename:funtion删除在filename文件的function函数处设定的断点

(5)clear line_number:删除在line_number行设定的断点

(6)clearfilename:line_number:删除在filename文件的line_number行设定的断点

4、禁用与启用断点

(1)disablebreakpoint-list(是用空格分隔开的多个断点标识符):禁用断点

(2)disable:禁用所有现存断点

(3)enablebreakpoint-list:启用断点

(4)enable oncebreakpoint-list:在下次引起GDB暂停执行后禁用

5、断点命令列表

让GDB在每次到达某个断点时自动执行一组命令,从而自动完成某一任务。

使用commands命令设置命令列表:

commands breakpoint_number

...

commands

...

end

例如以下代码:


我打算查看传递给fibonacci函数的值以及次序,但是不想在程序中插入printf语句并重新编译代码,可以这样做:

在该函数入口处设置一个断点,然后设置命令列表:


printf命令和C中printf函数类似,只是括号是可选的。

运行结果:


如果嫌GDB输出太冗长,可以使用silent命令,只需将其添加到设置的命令列表最开始处即可。

 

四、调试

1、启动:run

2、查看栈帧:frame num(栈帧编号)

注意栈帧编号规则,当前正在执行的函数的帧被编号为0,其父帧(即该函数的调用者的栈帧)被编号为1,父帧的父帧被编号为2,以此类推。

跳到调用栈中的下一个父帧:up

引向相反方向:down

显示整个栈,即当前存在的所有帧的集合:backtrace

3、输出当前值:print或者p

4、浏览以前的GDB命令:上一个Ctrl+P、下一个Ctrl+N

5、可以直接按下回车再次执行最近执行过的那条命令

6、运行

(1)单步执行:step(s)、next(n),仅执行到代码的下一行后再次暂停。

注意二者区别:在函数调用时step会进入函数,next导致下一次暂停出现在调用函数之后。next被称为单步越过(stepping over)函数,而step被称为单步进入(stepping into)函数。

next和step都可以采用一个可选的数值参数,来表示要使用next或step执行的额外行数。

(2)无条件恢复程序的执行:continue(c)

直到遇到另一个断点或者程序结束。

continue可以接受一个可选的数值参数n,要求GDB忽略下面n个断点。

(3)用finish(fin)或until(u)命令恢复。

finish命令指示GDB恢复执行,直到恰好在当前帧完成之后为止。

until命令通常用来在不进一步在循环中暂停(除了循环中的中间断点)的情况下完成正在执行的循环。until会执行循环的其余部分(如果遇到断点,还是会暂停),让GDB在循环后面的第一行代码处暂停。

until命令也可以接受源代码中的位置作为参数,其用法与break命令同。

比如下列代码清单swapflaw.c:


如果GDB触发了main函数入口处的一个断点,那么可以使用下面这些命令方便地使程序一直执行到swap()的入口:

until 13

until swap

until swapflaw.c:13

until swapflaw.c:swap

7、退出:quit

 

gdb常用操作