*提示:
gdb中,输入命令时,可以不用打全命令
在Linux下,可以敲击两次TAB键来补齐命令的全称
*在GDB中运行程序
r或是run命令
1、程序运行参数。
set args 可指定运行时参数。(如:set args 10 20 30 40 50)
show args 命令可以查看设置好的运行参数。
2、运行环境。
path <dir> 可设定程序的运行路径。
show paths 查看程序的运行路径。
set environment varname [=value] 设置环境变量。如:set env USER=hchen
show environment [varname] 查看环境变量。
3、程序的输入输出。
info terminal 显示你程序用到的终端的模式。
使用重定向控制程序输出。如:run > outfile
tty命令可以指写输入输出的终端设备。如:tty /dev/ttyb
*调试已运行的程序
gdb 程序 进程号
*设置断点
break <function>
break <linenum>
break +offset
break -offset
在当前行号的前面或后面的offset行停住。offiset为自然数。
break filename:linenum
break filename:function
break ... if <condition>
...可以是上述的参数,condition表示条件,在条件成立时停住。
比如在循环境体中,可以设置break if i=100,表示当i为100时停住程序。
查看断点时,可使用info命令,如下所示:(注:n表示断点号)
info breakpoints [n]
info break [n]
*设置观察点
watch <expr>
为表达式(变量)expr设置一个观察点。一量表达式值有变化时,马上停住程序。
rwatch <expr>
当表达式(变量)expr被读时,停住程序。
awatch <expr>
当表达式(变量)的值被读或被写时,停住程序。
info watchpoints
列出当前所设置了的所有观察点。
*维护停止点
clear
清除所有的已定义的停止点。
clear <function>
clear <filename:function>
清除所有设置在函数上的停止点。
delete [breakpoints] [range...]
删除指定的断点,breakpoints为断点号。如果不指定断点号,则表示删除所有的断点。
range 表示断点号的范围(如:3-7)。其简写命令为d。
一种方法是disable停止点,disable了的停止点,GDB不会删除,当你还需要时,enable即可。
disable [breakpoints] [range...]
disable所指定的停止点,breakpoints为停止点号。如果什么都不指定,表示disable所有的停止点。简写命令是dis.
enable [breakpoints] [range...]
enable所指定的停止点,breakpoints为停止点号。
*为停止点设定运行命令
以使用GDB提供的command命令来设置停止点的运行命令。也就是说,当运行的程序在被停止住时,
我们可以让其自动运行一些别的命令,这很有利行自动化调试
commands [bnum]
... command-list ...
end
为断点号bnum指写一个命令列表。当程序被该断点停住时,gdb会依次运行命令列表中的命令。
例如:
break foo if x>0
commands
printf "x is %d\n",x
continue
end
断点设置在函数foo中,断点条件是x>0,如果程序被断住后,也就是,一旦x的值在foo函数中大于0,GDB会自动打印出x的值,
并继续运行程序。如果你要清除断点上的命令序列,那么只要简单的执行一下commands命令,并直接在打个end就行了。
*恢复程序运行和单步调试
continue [ignore-count]
c [ignore-count]
恢复程序运行,直到程序结束,或是下一个断点到来。ignore-count表示忽略其后的断点次数。
step <count> s单步跟踪
next <count> n
finish 运行程序,直到当前函数完成返回。并打印函数返回时的堆栈地址和返回值及参数值等信息。
until 或 u 运行程序直到退出循环体。
*线程(Thread Stops)
break <linespec> thread <threadno>
break <linespec> thread <threadno> if ...
linespec指定了断点设置在的源程序的行号。threadno指定了线程的ID,注意,这个ID是GDB分配的,
你可以通过“info threads”命令来查看正在运行程序中的线程信息。如果你不指定thread <threadno>则表示你的断点
设在所有线程上面。你还可以为某线程指定断点条件。如:
(gdb) break frik.c:13 thread 28 if bartab > lim
当你的程序被GDB停住时,所有的运行线程都会被停住。这方便你你查看运行程序的总体情况。
而在你恢复程序运行时,所有的线程也会被恢复运行。那怕是主进程在被单步调试时。
*查看栈信息
backtrace
bt 打印当前的函数调用栈的所有信息
bt <n> n是一个正整数,表示只打印栈顶上n层的栈信息。
bt <-n> -n表一个负整数,表示只打印栈底下n层的栈信息。
查看某一层的信息,需切换当前栈,一般来说,程序停止时,最顶层的栈就是当前栈,如果要查看栈下面层的详细信息,
首先要做的是切换当前栈。
frame <n>
f <n>
n是一个从0开始的整数,是栈中的层编号。比如:frame 0,表示栈顶,frame 1,表示栈的第二层。
up <n> 表示向栈的上面移动n层,可以不打n,表示向上移动一层。
down <n> 表示向栈的下面移动n层,可以不打n,表示向下移动一层。
info f 打印出更为详细的当前栈层的信息
info args 打印出当前函数的参数名及其值。
info locals 打印出当前函数中所有局部变量及其值。
*显示源代码
list <linenum> 显示程序第linenum行的周围的源程序。
list <function> 显示函数名为function的函数的源程序。
list 显示当前行后面的源程序。
list - 显示当前行前面的源程序。
list <first>, <last> 显示从first行到last行之间的源代码。
set listsize <count> 设置一次显示源代码的行数。
*指定源文件的路径
dir <dirname ... > 加一个源文件路径到当前路径的前面。如果你要指定多个路径,UNIX下你可以使用“:”
show directories 显示定义了的源文件搜索路径。
*源代码的内存
(gdb) info line tst.c:func 查看源代码在内存中的地址
info line后面可以跟“行号”,“函数名”,“文件名:行号”,“文件名:函数名”,
这个命令会打印出所指定的源码在运行时的内存地址.
*查看运行时数据
print <expr>
print /<f> <expr>
表达式中,有几种GDB所支持的操作符
@ 是一个和数组有关的操作符,在后面会有更详细的说明。
:: 指定一个在文件或是一个函数中的变量。
{<type>} <addr> 表示一个指向内存地址<addr>的类型为type的一个对象。
*程序变量:
在GDB中,你可以随时查看以下三种变量的值:
1、全局变量(所有文件可见的)
2、静态全局变量(当前文件可见的)
3、局部变量(当前Scope可见的)
查看全局变量的值时,你可以使用“::”操作符:
file::variable
function::variable
例如,查看文件f2.c中的全局变量x的值: gdb) p 'f2.c'::x
*数组
int *array = (int *) malloc (len * sizeof (int));
在GDB调试过程中,你可以以如下命令显示出这个动态数组的取值:
p *array@len
*输出格式
x 按十六进制格式显示变量。
d 按十进制格式显示变量。
u 按十六进制格式显示无符号整型。
o 按八进制格式显示变量。
t 按二进制格式显示变量。
a 按十六进制格式显示变量。
c 按字符格式显示变量。
f 按浮点数格式显示变量。
*查看内存
examine命令(简写是x)来查看内存地址中的值
x/<n/f/u> <addr>
n、f、u是可选的参数。
n 是一个正整数,表示显示内存的长度,也就是说从当前地址向后显示几个地址的内容。
f 表示显示的格式,参见上面。如果地址所指的是字符串,那么格式可以是s,如果地十是指令地址,那么格式可以是i。
u 表示从当前地址往后请求的字节数,如果不指定的话,GDB默认是4个bytes。u参数可以用下面的字符来代替,
b表示单字节,
h表示双字节,
w表示四字节,
g表示八字节。
当我们指定了字节长度后,GDB会从指内存定的内存地址开始,读写指定字节,并把其当作一个值取出来。
<addr>表示一个内存地址。
n/f/u三个参数可以一起使用。例如:
命令:x/3uh 0x54320 表示,从内存地址0x54320读取内容,h表示以双字节为一个单位,3表示三个单位,u表示按十六进制显示。
*自动显示
display <expr>
display/<fmt> <expr>
display/<fmt> <addr> expr是一个表达式,fmt表示显示的格式,addr表示内存地址
display/i $pc 一个非常有用的命令, $pc是GDB的环境变量,表示着指令的地址,/i则表示输出格式为机器指令码,
也就是汇编。于是当程序停下后,就会出现源代码和机器指令码相对应的情形。
undisplay <dnums...>
delete display <dnums...> 删除自动显示,dnums意为所设置好了的自动显式的编号。如果要同时删除几个,
编号可以用空格分隔,如果要删除一个范围内的编号,可以用减号表示(如:2-5)
disable display <dnums...>
enable display <dnums...>
disable和enalbe 不删除自动显示的设置,而只是让其失效和恢复。
info display 查看display设置的自动显示的信息。GDB会打出一张表格,向你报告当然调试中设置了多少个自动显示设置,
其中包括,设置的编号,表达式,是否enable。
*GDB环境变量
以在GDB的调试环境中定义自己的变量,用来保存一些调试程序中的运行数据。要定义一个GDB的变量很简单只需。
使用GDB的set命令。GDB 的环境变量和UNIX一样,也是以$起头。如:
set $foo = *object_ptr
使用环境变量时,GDB会在你第一次使用时创建这个变量,而在以后的使用中,则直接对其賦值。环境变量没有类型,你可以给环 境变量定义任一的类型。包括结构体和数组。
show convenience 该命令查看当前所设置的所有的环境变量。
这是一个比较强大的功能,环境变量和程序变量的交互使用,将使得程序调试更为灵活便捷。例如:
set $i = 0
print bar[$i++]->contents
于是,当你就不必,print bar[0]->contents, print bar[1]->contents地输入命令了。输入这样的命令后,只用敲回车,
重复执行上一条语句,环境变量会自动累加,从而完成逐个输出的功能。
*修改变量值
(gdb) print x=4
gdb中,输入命令时,可以不用打全命令
在Linux下,可以敲击两次TAB键来补齐命令的全称
*在GDB中运行程序
r或是run命令
1、程序运行参数。
set args 可指定运行时参数。(如:set args 10 20 30 40 50)
show args 命令可以查看设置好的运行参数。
2、运行环境。
path <dir> 可设定程序的运行路径。
show paths 查看程序的运行路径。
set environment varname [=value] 设置环境变量。如:set env USER=hchen
show environment [varname] 查看环境变量。
3、程序的输入输出。
info terminal 显示你程序用到的终端的模式。
使用重定向控制程序输出。如:run > outfile
tty命令可以指写输入输出的终端设备。如:tty /dev/ttyb
*调试已运行的程序
gdb 程序 进程号
*设置断点
break <function>
break <linenum>
break +offset
break -offset
在当前行号的前面或后面的offset行停住。offiset为自然数。
break filename:linenum
break filename:function
break ... if <condition>
...可以是上述的参数,condition表示条件,在条件成立时停住。
比如在循环境体中,可以设置break if i=100,表示当i为100时停住程序。
查看断点时,可使用info命令,如下所示:(注:n表示断点号)
info breakpoints [n]
info break [n]
*设置观察点
watch <expr>
为表达式(变量)expr设置一个观察点。一量表达式值有变化时,马上停住程序。
rwatch <expr>
当表达式(变量)expr被读时,停住程序。
awatch <expr>
当表达式(变量)的值被读或被写时,停住程序。
info watchpoints
列出当前所设置了的所有观察点。
*维护停止点
clear
清除所有的已定义的停止点。
clear <function>
clear <filename:function>
清除所有设置在函数上的停止点。
delete [breakpoints] [range...]
删除指定的断点,breakpoints为断点号。如果不指定断点号,则表示删除所有的断点。
range 表示断点号的范围(如:3-7)。其简写命令为d。
一种方法是disable停止点,disable了的停止点,GDB不会删除,当你还需要时,enable即可。
disable [breakpoints] [range...]
disable所指定的停止点,breakpoints为停止点号。如果什么都不指定,表示disable所有的停止点。简写命令是dis.
enable [breakpoints] [range...]
enable所指定的停止点,breakpoints为停止点号。
*为停止点设定运行命令
以使用GDB提供的command命令来设置停止点的运行命令。也就是说,当运行的程序在被停止住时,
我们可以让其自动运行一些别的命令,这很有利行自动化调试
commands [bnum]
... command-list ...
end
为断点号bnum指写一个命令列表。当程序被该断点停住时,gdb会依次运行命令列表中的命令。
例如:
break foo if x>0
commands
printf "x is %d\n",x
continue
end
断点设置在函数foo中,断点条件是x>0,如果程序被断住后,也就是,一旦x的值在foo函数中大于0,GDB会自动打印出x的值,
并继续运行程序。如果你要清除断点上的命令序列,那么只要简单的执行一下commands命令,并直接在打个end就行了。
*恢复程序运行和单步调试
continue [ignore-count]
c [ignore-count]
恢复程序运行,直到程序结束,或是下一个断点到来。ignore-count表示忽略其后的断点次数。
step <count> s单步跟踪
next <count> n
finish 运行程序,直到当前函数完成返回。并打印函数返回时的堆栈地址和返回值及参数值等信息。
until 或 u 运行程序直到退出循环体。
*线程(Thread Stops)
break <linespec> thread <threadno>
break <linespec> thread <threadno> if ...
linespec指定了断点设置在的源程序的行号。threadno指定了线程的ID,注意,这个ID是GDB分配的,
你可以通过“info threads”命令来查看正在运行程序中的线程信息。如果你不指定thread <threadno>则表示你的断点
设在所有线程上面。你还可以为某线程指定断点条件。如:
(gdb) break frik.c:13 thread 28 if bartab > lim
当你的程序被GDB停住时,所有的运行线程都会被停住。这方便你你查看运行程序的总体情况。
而在你恢复程序运行时,所有的线程也会被恢复运行。那怕是主进程在被单步调试时。
*查看栈信息
backtrace
bt 打印当前的函数调用栈的所有信息
bt <n> n是一个正整数,表示只打印栈顶上n层的栈信息。
bt <-n> -n表一个负整数,表示只打印栈底下n层的栈信息。
查看某一层的信息,需切换当前栈,一般来说,程序停止时,最顶层的栈就是当前栈,如果要查看栈下面层的详细信息,
首先要做的是切换当前栈。
frame <n>
f <n>
n是一个从0开始的整数,是栈中的层编号。比如:frame 0,表示栈顶,frame 1,表示栈的第二层。
up <n> 表示向栈的上面移动n层,可以不打n,表示向上移动一层。
down <n> 表示向栈的下面移动n层,可以不打n,表示向下移动一层。
info f 打印出更为详细的当前栈层的信息
info args 打印出当前函数的参数名及其值。
info locals 打印出当前函数中所有局部变量及其值。
*显示源代码
list <linenum> 显示程序第linenum行的周围的源程序。
list <function> 显示函数名为function的函数的源程序。
list 显示当前行后面的源程序。
list - 显示当前行前面的源程序。
list <first>, <last> 显示从first行到last行之间的源代码。
set listsize <count> 设置一次显示源代码的行数。
*指定源文件的路径
dir <dirname ... > 加一个源文件路径到当前路径的前面。如果你要指定多个路径,UNIX下你可以使用“:”
show directories 显示定义了的源文件搜索路径。
*源代码的内存
(gdb) info line tst.c:func 查看源代码在内存中的地址
info line后面可以跟“行号”,“函数名”,“文件名:行号”,“文件名:函数名”,
这个命令会打印出所指定的源码在运行时的内存地址.
*查看运行时数据
print <expr>
print /<f> <expr>
表达式中,有几种GDB所支持的操作符
@ 是一个和数组有关的操作符,在后面会有更详细的说明。
:: 指定一个在文件或是一个函数中的变量。
{<type>} <addr> 表示一个指向内存地址<addr>的类型为type的一个对象。
*程序变量:
在GDB中,你可以随时查看以下三种变量的值:
1、全局变量(所有文件可见的)
2、静态全局变量(当前文件可见的)
3、局部变量(当前Scope可见的)
查看全局变量的值时,你可以使用“::”操作符:
file::variable
function::variable
例如,查看文件f2.c中的全局变量x的值: gdb) p 'f2.c'::x
*数组
int *array = (int *) malloc (len * sizeof (int));
在GDB调试过程中,你可以以如下命令显示出这个动态数组的取值:
p *array@len
*输出格式
x 按十六进制格式显示变量。
d 按十进制格式显示变量。
u 按十六进制格式显示无符号整型。
o 按八进制格式显示变量。
t 按二进制格式显示变量。
a 按十六进制格式显示变量。
c 按字符格式显示变量。
f 按浮点数格式显示变量。
*查看内存
examine命令(简写是x)来查看内存地址中的值
x/<n/f/u> <addr>
n、f、u是可选的参数。
n 是一个正整数,表示显示内存的长度,也就是说从当前地址向后显示几个地址的内容。
f 表示显示的格式,参见上面。如果地址所指的是字符串,那么格式可以是s,如果地十是指令地址,那么格式可以是i。
u 表示从当前地址往后请求的字节数,如果不指定的话,GDB默认是4个bytes。u参数可以用下面的字符来代替,
b表示单字节,
h表示双字节,
w表示四字节,
g表示八字节。
当我们指定了字节长度后,GDB会从指内存定的内存地址开始,读写指定字节,并把其当作一个值取出来。
<addr>表示一个内存地址。
n/f/u三个参数可以一起使用。例如:
命令:x/3uh 0x54320 表示,从内存地址0x54320读取内容,h表示以双字节为一个单位,3表示三个单位,u表示按十六进制显示。
*自动显示
display <expr>
display/<fmt> <expr>
display/<fmt> <addr> expr是一个表达式,fmt表示显示的格式,addr表示内存地址
display/i $pc 一个非常有用的命令, $pc是GDB的环境变量,表示着指令的地址,/i则表示输出格式为机器指令码,
也就是汇编。于是当程序停下后,就会出现源代码和机器指令码相对应的情形。
undisplay <dnums...>
delete display <dnums...> 删除自动显示,dnums意为所设置好了的自动显式的编号。如果要同时删除几个,
编号可以用空格分隔,如果要删除一个范围内的编号,可以用减号表示(如:2-5)
disable display <dnums...>
enable display <dnums...>
disable和enalbe 不删除自动显示的设置,而只是让其失效和恢复。
info display 查看display设置的自动显示的信息。GDB会打出一张表格,向你报告当然调试中设置了多少个自动显示设置,
其中包括,设置的编号,表达式,是否enable。
*GDB环境变量
以在GDB的调试环境中定义自己的变量,用来保存一些调试程序中的运行数据。要定义一个GDB的变量很简单只需。
使用GDB的set命令。GDB 的环境变量和UNIX一样,也是以$起头。如:
set $foo = *object_ptr
使用环境变量时,GDB会在你第一次使用时创建这个变量,而在以后的使用中,则直接对其賦值。环境变量没有类型,你可以给环 境变量定义任一的类型。包括结构体和数组。
show convenience 该命令查看当前所设置的所有的环境变量。
这是一个比较强大的功能,环境变量和程序变量的交互使用,将使得程序调试更为灵活便捷。例如:
set $i = 0
print bar[$i++]->contents
于是,当你就不必,print bar[0]->contents, print bar[1]->contents地输入命令了。输入这样的命令后,只用敲回车,
重复执行上一条语句,环境变量会自动累加,从而完成逐个输出的功能。
*修改变量值
(gdb) print x=4