
第一步 编译一个死循环程序。
/ File name mallocc/
#include <stdioh>
#include <stdlibh>
#include <stringh>
void getmem(void p, int num){
p = (void )malloc(num);
}
void test(void){
char str = NULL;
getmem((void )&str, 100);
strcpy(str, "Hello");
printf("%s\n", str);
}
int main(void){
int i = 0;
while(1){
if (i == 1){
test();
return 1;
}
}
return 0;
}
我们可以看出,这个程序就是malloc一段内存空间,用来供strcpy使用,由于只是调试一下,就没有在test程序中加上一些关于strcpy的正确性判断语句。
函数的正常退出的情况是i==1,但是程序运行过程中根本无法使i==1成立。i的变量的值将会在使用gdb时用到。
开始编译
$gcc -g mallocc
得用gdb,加上-g还是需要的。生成的可执行文件为aout
第二步 让gdb连接到正在执行的进程上去
首先运行程序。
$/aout
明显的,是一个死循环。
重新开一个shell
$ps -u
我的机器的运行情况如下所示:
Warning: bad ps syntax, perhaps a bogus '-' See >
当然是看GDB的官方文档最权威,最全面咯
GDB User Manual
下载地址:>
首先要设置断点,可以双击某一行代码进行设置,或再双击取消有了断点后,系统运行到断点就会自动停止之后就可以按单步调试了。一般可以使用快捷功能键,对于Keil4来说: F10:在当前函数中单步运行,不进入子程序 F11:单步追踪,可以追踪到子程序 F9:继续全速运行,到下一断点自动停止以上功能均可以在Debug菜单中找到。另外还有运行、暂停、跳出子函数、运行到当前光标所在位置等功能
分类: 电脑/网络 >> *** 作系统/系统故障
问题描述:
第一次在Linux上工作,要用到一个什么gdb的东东。gdb到底是什么呢,各位老大?
解析:
Linux 包含了一个叫 gdb 的 GNU 调试程序 gdb 是一个用来调试 C 和 C++ 程序的强力调试器 它使你能在程序运行时观察程序的内部结构和内存的使用情况 以下是 gdb 所提供的一些功能:
它使你能监视你程序中变量的值
它使你能设置断点以使程序在指定的代码行上停止执行
它使你能一行行的执行你的代码
在命令行上键入 gdb 并按回车键就可以运行 gdb 了, 如果一切正常的话, gdb 将被启动并且你将在屏幕上看到类似的内容:
GDB is free sofare and you are wele to distribute copies of it
under certain conditions; type "show copying" to see the conditions
There is absolutely no warranty for GDB; type "show warranty" for details
GDB 414 (i486-slakware-linux), Copyright 1995 Free Sofare Foundation, Inc
(gdb)
当你启动 gdb 后, 你能在命令行上指定很多的选项 你也可以以下面的方式来运行 gdb :
gdb <fname>
当你用这种方式运行 gdb , 你能直接指定想要调试的程序 这将告诉gdb 装入名为 fname 的可执行文件 你也可以用 gdb 去检查一个因程序异常终止而产生的 core 文件, 或者与一个正在运行的程序相连 你可以参考 gdb 指南页或在命令行上键入 gdb -h 得到一个有关这些选项的说明的简单列表
1、停住的时候,当前的线程未必一定是出问题的那个线程,所以bt是看不见什么的。先试试看能不能用info thread找出你自己的线程。
2、gdb多次连接应该是没有问题的。看你说的问题像是之前的连接还没有完全断开。
3、如果可以修改源代码,多加几个log或许可以找到出问题的大概位置。
1: 对于在应用程序中加入参数进行调试的方法:
直接用 gdb app -p1 -p2 这样进行调试是不行的。
需要像以下这样使用:
#gdb app
(gdb) r -p1 -p2
或者在运行run命令前使用set args命令:
(gdb) set args p1 p2
可以用show args 命令来查看
2 加入断点:
break <linenumber>
break <funcName>
break +offset
break -offset
(在当前行号的前面或后面的offset行停住。)
break filename:linenum
在源文件filename的linenum行处停住。
break filename:function
在源文件filename的function函数的入口处停住。
break if
可以是上述的参数,condition表示条件,在条件成立时停住。比如在循环境体中,可以设置 break if i=100,表示当i为100时停住程序。
3 查看运行时的堆栈:
使用bt命令
4 打印某个变量的值:
print val
5 单步: n
继续运行: c
step
单步跟踪,如果有函数调用,他会进入该函数。
next
同样单步跟踪,如果有函数调用,他不会进入该函数。很像VC等工具中的step over。后面可以加count也可以不加,不加表示一条条地执行,加表示执行后面的count条指令,然后再停住。
set step-mode
set step-mode on
打开step-mode模式,于是,在进行单步跟踪时,程序不会因为没有debug信息而不停住。这个参数有很利于查看机器码。
set step-mod off
关闭step-mode模式。
finish
运行程序,直到当前函数完成返回。并打印函数返回时的堆栈地址和返回值及参数值等信息。
until 或 u
当你厌倦了在一个循环体内单步跟踪时,这个命令可以运行程序直到退出循环体。
6在GDB中执行shell命令:
在gdb环境中,你可以执行UNIX的shell的命令,使用gdb的shell命令来完成:
eg shell make
7 运行环境
可设定程序的运行路径。
show paths 查看程序的运行路径。
set environment varname [=value] 设置环境变量。如:set env USER=hchen
show environment [varname] 查看环境变量。
8观察点(WatchPoint)
观察点一般来观察某个表达式(变量也是一种表达式)的值是否有变化了,如果有变化,马上停住程 序。我们有下面的几种方法来设置观察点:
watch
为表达式(变量)expr设置一个观察点。一量表达式值有变化时,马上停住程序。
rwatch
当表达式(变量)expr被读时,停住程序。
awatch
当表达式(变量)的值被读或被写时,停住程序。
info watchpoints
列出当前所设置了的所有观察点。
9 维护breakpoint
clear
清除所有的已定义的停止点。
clear func
清除所有设置在函数上的停止点。
delete [breakpoints] [range]
删除指定的断点,breakpoints为断点号。如果不指定断点号,则表示删除所有的断点。range 表示断点号的范围(如:3-7)。其简写命令为d。
比删除更好的一种方法是disable停止点,disable了的停止点,GDB不会删除,当你还需要时,enable即可,就好像回收站一样。
disable [breakpoints] [range]
disable所指定的停止点,breakpoints为停止点号。如果什么都不指定,表示disable所有的停止 点。简写命令是dis
enable [breakpoints] [range]
enable所指定的停止点,breakpoints为停止点号。
10、程序变量
查看文件中某变量的值:
file::variable
function::variable
可以通过这种形式指定你所想查看的变量,是哪个文件中的或是哪个函数中的。例如,查看文件f2c中的全局变量x的值:
gdb) p 'f2c'::x
查看数组的值
有时候,你需要查看一段连续的内存空间的值。比如数组的一段,或是动态分配的数据的大小。你可以使用GDB的“@” *** 作符,“@”的左边是第一个内存的地址的值,“@”的右边则你你想查看内存的长度。例如,你的程序中有这样的语句:
int array = (int ) malloc (len sizeof (int));
于是,在GDB调试过程中,你可以以如下命令显示出这个动态数组的取值:
p array@len
如果是静态数组的话,可以直接用print数组名,就可以显示数组中所有数据的内容了。
11输出格式
一般来说,GDB会根据变量的类型输出变量的值。但你也可以自定义GDB的输出的格式。例如,你想输出一个整数的十六进制,或是二进制来查看这个整型变量的中的位的情况。要做到这样,你可以使用GDB的数据显示格式:
x 按十六进制格式显示变量。
d 按十进制格式显示变量。
u 按十六进制格式显示无符号整型。
o 按八进制格式显示变量。
t 按二进制格式显示变量。
a 按十六进制格式显示变量。
c 按字符格式显示变量。
f 按浮点数格式显示变量。
(gdb) p i
$21 = 101
(gdb) p/a i
$22 = 0x65
(gdb) p/c i
$23 = 101 'e'
(gdb) p/f i
$24 = 141531145e-43
(gdb) p/x i
$25 = 0x65
(gdb) p/t i
$26 = 1100101
11查看内存
使用examine命令(简写是x)来查看内存地址中的值。x命令的语法如下所示:
x/
n、f、u是可选的参数。
n 是一个正整数,表示显示内存的长度,也就是说从当前地址向后显示几个地址的内容。
f 表示显示的格式,参见上面。如果地址所指的是字符串,那么格式可以是s,如果地十是指令地址,那么格式可以是i。
u 表示从当前地址往后请求的字节数,如果不指定的话,GDB默认是4个bytes。u参数可以用下面的字符来代替,b表示单字节,h表示双字节,w表示四字节,g表示八字节。当我们指定了字节长度后,GDB会从指内存定的内存地址开始,读写指定字节,并把其当作一个值取出来。
n/f/u三个参数可以一起使用。例如:
命令:x/3uh 0x54320 表示,从内存地址0x54320读取内容,h表示以双字节为一个单位,3表示三个单位,u表示按十六进制显示。
12自动显示
你可以设置一些自动显示的变量,当程序停住时,或是在你单步跟踪时,这些变量会自动显示。相关的GDB命令是display。
display
display/
display/ expr
expr是一个表达式,fmt表示显示的格式,addr表示内存地址,当你用display设定好了一个或多个表达式后,只要你的程序被停下来,GDB会自动显示你所设置的这些表达式的值。
格式i和s同样被display支持,一个非常有用的命令是:
display/i $pc
undisplay
delete display
删除自动显示,dnums意为所设置好了的自动显式的编号。
disable display
enable display
disable和enalbe不删除自动显示的设置,而只是让其失效和恢复。
info display
查看display设置的自动显示的信息。GDB会打出一张表格,向你报告当然调试中设置了多少个自动显示设置,其中包括,设置的编号,表达式,是否enable。
13 设置显示选项
set print address
set print address on
打开地址输出,当程序显示函数信息时,GDB会显出函数的参数地址。系统默认为打开的,
show print address
查看当前地址显示选项是否打开。
set print array
set print array on
打开数组显示,打开后当数组显示时,每个元素占一行,如果不打开的话,每个元素则以逗号分隔。这个选项默认是关闭的。与之相关的两个命令如下,我就不再多说了。
set print array off
show print array
set print elements
这个选项主要是设置数组的,如果你的数组太大了,那么就可以指定一个来指定数据显示的最大长度,当到达这个长度时,GDB就不再往下显示了。如果设置为0,则表示不限制。
show print elements
查看print elements的选项信息。
set print null-stop
如果打开了这个选项,那么当显示字符串时,遇到结束符则停止显示。这个选项默认为off。
set print pretty on
如果打开printf pretty这个选项,那么当GDB显示结构体时会比较漂亮。
14关于显示源码list
本文参考《Debug Hacks》一书所作 —— 每天进步一点点。
一 准备
通过 gcc 的 -g 选项生成调试信息。
$ gcc -Wall -O2 -g 源文件
-g选项可以使用仅可GDB使用的一些附加调试信息;这些附加信息可以使GDB工作的更好,但是也可能令其他调试器崩溃或者不能读该文件。
二 GDB基本用法
启动:
$ gdb 可执行文件名
设置断点:
(gdb) break 断点
程序运行后,到达断点就会自动暂停运行。此时就可以查看该时刻的变量值,显示栈针,重新设置断点或者重新运行等。
断点可以通过函数名,文件内的行号来设置,也可以先指定文件名再指定行号,还可以指定与暂停位置的偏移量,或者用地址来设置。
(gdb) break 函数名
(gdb) break 行号
(gdb) break 文件名:行号
(gdb) break 文件名:函数名
(gdb) break +偏移量
(gdb) break -偏移量
(gdb) break 地址
在设置断点的时候,如果不指定断点位置,就在下一行代码上设置断点。
条件断点
(gdb) break 断点 if 条件
仅在特定条件下中断。对于已存在的断点,可使用condition为其添加条件。
(gdb) break 断点编号 条件
而删除指定编号断点的触发条件同样使用condition。
(gdb) condition 断点编号
查询断点
(gdb) info break
监视点
要想找到变量在何处被改变,可以使用 watch 命令(监视点, watchpoint)。
(gdb) watch <表达式>
<表达式>发生变化时暂停运行。<表达式>的意思是常量或变量等。
(gdb) awatch <表达式>
<表达式>被访问、改变时暂停运行。
(gdb) rwatch <表达式>
<表达式>被访问时暂停运行。
删除断点和监视点
用 delete 命令删除断点和监视点。
(gdb) delete <编号>
运行
(gdb) run 参数
用 run 命令开始运行。执行run,就会执行到设置了断点的位置后暂停运行。
经常用到的一个 *** 作是在main()上设置断点,然后执行到main()函数暂停。按照上面的内容, *** 作命令有:
(gdb) break main
(gdb) run
对于执行到 main() 函数暂停的 *** 作,我们可以使用 start 命令达到同样的效果。
(gdb) start
显示栈帧
backtrace 命令可以在遇到断点而暂停执行时显示栈帧。此外,backtrace 的别名还有 where 和 info stack。
(gdb) backtrace
显示所有栈帧。
(gdb) backtrace N
只显示开头 N 个栈帧。
(gdb) backtrace -N
只显示最后 N 个栈帧。
(gdb) backtrace full
(gdb) backtrace full N
(gdb) backtrace full -N
不仅显示backtrace,还有显示局部变量。
显示栈帧之后,就可以看出程序在何处停止(即断点的位置),以及程序的调用路径。
显示变量
print 命令可以显示变量。
(gdb) print 变量
显示寄存器
info registers可以显示寄存器。
(gdb) info registers
单步执行
单步执行的意思是根据源代码一行一行地执行。
执行源代码中一行的命令为 next 。执行时如果遇到函数调用,可能想执行到函数内部,此时可以使用 step 命令。
next 命令和 step 命令都是执行源代码中的一行。如果要逐条执行汇编指令,可以分别使用 nexti 和 stepi 命令。
继续运行
调试时,可以使用 continue 命令继续运行程序。程序会在遇到断点后再次暂停运行。如果没有遇到断点,就会一直运行到结束。
(gdb) continue
(gdb) continue 次数
指定次数可以忽略断点。例如, continue 5 则 5 次遇到断点不停止,第 6 次遇到断点时才暂停执行。
以上就是关于如何gdb调试一个运行中的进程全部的内容,包括:如何gdb调试一个运行中的进程、程序调试 | GDB常用命令备忘录、GDB如何实现对程序的调试设置断点,单步执行等等。等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)