收藏 分享(赏)

linux下GDB教程.pdf

上传人:HR专家 文档编号:6298262 上传时间:2019-04-05 格式:PDF 页数:26 大小:268.39KB
下载 相关 举报
linux下GDB教程.pdf_第1页
第1页 / 共26页
linux下GDB教程.pdf_第2页
第2页 / 共26页
linux下GDB教程.pdf_第3页
第3页 / 共26页
linux下GDB教程.pdf_第4页
第4页 / 共26页
linux下GDB教程.pdf_第5页
第5页 / 共26页
点击查看更多>>
资源描述

1、GDBGDB教程GDB是一个强大的命令行调试工具。大家知道命令行的强大就是在于,其可以形成执行序列,形成脚本。UNIX下的软件全是命令行的,这给程序开发提供了极大的便利,命令行软件的优势在于,他们可以非常容易的集成在一起,使用几个简单的已有工具的命令,就可以做出一个非常强大的功能。于是UNIX下的软件比windows下的软件更能有机的结合,各自发挥各自的长处,组合成更为强筋的功能。而i s下的图形软件基本上各自为营,互相不能条用,很不利于各种软件的相互集成。在这里并不是要和windows做个什么比较,所谓“寸有所长,尺有所短”,图形化工具还是有不如命令行的地方。用GDBGDB调试程序BGDB概

2、述GDB是GNU开源组织发布的一个强大的UNIX下调试程序工具。或许各位比较喜欢那种图形界面方式的,像VC,BC等IDE的调试,但如果你是在UNIX平台下作软件,你会发现GDB这个调试工具有比V,BC的图形化调试器更强大的功能。所谓“寸有所长,尺有所短”就是这个道理。一般来说,GDB主要帮助你完成下面四个方面的功能:1、启动你的程序,可以按照你自定义的要求随心所欲的运行程序。2、可以让调试程序在你所指定的位置的断点处停止。3、当程序停止时,可以检查此时你的程序中所发生的事情。4、动态的改变你程序的执行环境。从上面看来,GDB和一般的调试工具没有什么两样,基本上也是完成这些功能,不过在细节上,你

3、会发现这个调试工具的强大,大家可能习惯图形化的调试工具,但有时候,命令行的调试工具却有着图形化工具所不能完成的功能。让我们来看一个例子:源程序:test.c1#includ23intfunc(int)45intsum=0,i;6for(i;igccgtest.cotest使用GDB调试:gdbtest启动GDBGNUgdb5.1.Copyriht202FreSoftwareFoundation,Ic.GDBisfresoftwar,covrdbytheGNUGenralPublicLicense,andyouarewelcomtochngeitand/oristriutcopisofitnde

4、rcertaicoits.Typ“shwcopyi“toseetheconditons.herisabsolutelynwarntyforGDB.Type“showarnty“fordetails.TisGDBwscofigureds“i386-suse-linux“.(gdb)(gdb)list从第一行列出源码1#include23intfunc(int)45 intsum=0,i;6 for(i;iprogram也就是你的执行文件,一般在当前目录下。2、gdbcore用gdb同时调试一个运行程序和core文件,core是程序非法执行后coredump后产生的文件。3、gdb如果你的程序是一

5、个服务程序,那么你可以指定这个服务程序运行时的进程ID。gdb会自动atch上去,并调试它。program应该在PATH环境变量中搜索到。GDB启动时,可以加上一些GDB的启动开关,详细的开关可以用gdbhelp来查看。下面只列举一些比较常用的参数:-symbols-s从指定文件中读取符号表。-sefile从指定文件中读取符号表信息,并把他用在可执行文件中。-core-cfile调试coredump的core文件。-directory-d加入一个源文件的搜索路径。默认搜索路径是环境变量中PATH所定义的路径。GDB的命令概貌启动gdb后,就进入了gdb的调试环境,就可以使用gdb的命令开始调试

6、程序了,gdb的命令可以使用help命令来查看,如下所示:(gdb)(gdb)helpListofclasesofcommands:alise-Aliaseofothercommandsbreakpoints-Makingprograstopatcertainpointsdata-Examiningdatafiles-Specifyingandexaminingfilesinternals-Maintenancecomandsobscure-Obscurefaturesrunning-Runningtheprogramstack-Examiningthestackstaus-Stausinqu

7、iriessupport-upportfaciltiestracepoints-Tracingofprogramexecutionwithoutstoppingtheprogramuser-defined-User-definedcomandsType“help“followedbyaclasnameforalistofcommandsinthatclas.ype“help“folledbycomandnaeforfulldocumentation.Commandnameabbreviationsarealowedifunambiguous.(gdb)(gdb)gdb的命令很多,gdb把之分成

8、很多种类。help命令只是列出了gdb的命令种类,如果要看种类中的命令,使用help命令,如:helpbreakpoints,查看设置断点的所有命令。也可以直接help来查看命令的帮助。Gdb中,输入命令时,可以不用打全命令,只用打命令的前几个字符就可以了,当然,命令的前几个字符要标志着一个唯一的命令,在linux下,可以敲击两次TAB键来补齐命令的全称,如果有重复的,gdb会把其列出来。示例一:在进入函数func时,设置一个断点。可以敲击breakfunc,或者直接就是bfunc(gdb)(gdb)funcBreakpoint1at0x804858:filehlo.c,line10.示例二:

9、敲入b按两次TAB键,你会看到所有b开头的命令:(gdb)(gdb)backtracebreakbt示例三:只记得函数的前缀,可以这样:(gdb)(gdb)make_make_section_from_filemake_environkeabs_secti kefucti_typemake_lockvector make_pointertykecleanup kerefrce_typemake_comd make_symbolcomltion_list(gdb)(gdb)ake_GDB把所有make开头的函数全部列出来给你查看。示例四:调试C+程序,可以函数名一样。如:(gdb)(gdb)bu

10、bble(ule(doubl,double)buble(int,it)(gdb)(gdb)bubble你可以查看到C+中所有的重载函数以及参数要退出GDB,只要quit或命令简称q就行了。GDBGDB中运行UNIXUNIX的ShelShel程序在gdb环境中,你可以执行UNIX的shel命令,使用gdb的shel命令来完成:shel调用UNIX的shel来执行,环境变量SHEL中定义的UNIX的shel将会被用来执行,如果SHEL没有定义,那就使用UNIX的标准shel:/bin/sh还有一个gdb命令是make:make可以在gdb中执行make命令来重新build自己的程序。这个命令等价于

11、“makemake”在GDBGDB中运行程序当以gdb方式启动gdb后,gdb会在PATH路径和当前目录中所搜的源文件。如要确认gdb是否读到源文件,可使用l或者list命令,看gdb是否能列出源代码。在gdb中,运行程序使用r或者run命令,程序的运行,有可能需要设置下面四方面的事:1、程序的运行参数。setargs可指定运行时参数。(如:setargs1020304050)showargs命令可以查看设置好的运行参数。2、运行环境path可设定程序的运行路径。showpaths查看程序的运行路径。setnvironmentvarname=value设置环境变量。如:setnvUSER=hc

12、henshowenvirentvarnae查看环境变量3、工作目录cd相当于shel的cd命令。pwd显示当前的工作目录。4、程序的输入输出infoterminal显示程序用到的终端的模式使用重定向空值程序输出。如runoutfilety命令可以指定写输入输出的终端设备。如ty/dev/tyb调试已运行的程序两种方法:1、在UNIX下用ps查看正在运行的程序的PID(进程ID),然后用gdbPID格式挂接正在运行的程序。2、先用gdb关联上源代码,并进行gdb,在gdb中用atch命令来挂接进程的PID,并用detach来取消挂接的程序。暂停/恢复程序运行调试程序中,暂停进程运行时必须的,GD

13、B可以方便的暂停程序的运行。你可以设置程序在哪停住,在什么条件下停住,在收到什么信号时停住等等。你便于你查看运行的变量,以及运行时的流程。当进程被gdb停住时,你可以使用infoprogram来查看程序是否在运行、进程号、被暂停的原因。在gdb中,我们可以有以下几种暂停方式:断点(breakpoint)、观察点(watchpoint)、捕捉点(cathpoint)、信号(signals)、线程停止(threadstops)。如果要恢复程序运行,可以使用c或者continue命令。一、设置断点(breakpointbreakpoint)我们用break命令设置断点。下面有几点设置断点的方法:br

14、eak在进入指定函数时停住。C+中可以使用clas:function或function(type,type)格式来指定函数名。break在指定行号停住。break+offsetbreakoffset在当前行号的前面或者后面的offset行停住。Ofset为自然数。breakfilename:lineum在源文件filenae的linenum行处停住。breakfilename:function在源文件filame的function函数的入口处停住。break*adress在程序运行的内存地址处停住。breakrk命令没有参数时,表示在下一条指令处停住。break if可以是上述的参数,cond

15、iton表示条件,在条件成立时停住。比如在循环体中,可以设置breakifi=10,表示当i为10时停住程序。查看断点时,可使用命令info命令,如下所示:(注:n表示断点号)infobreakpointsnifrk二、设置捕捉点(catchpointcatchpoint)我们可以设置捕捉点来捕捉程序运行时的一些事件。如:载入共享库(动态链接库)或是C+的一场,设置捕捉点的格式为:cath当evnt发生时,停住程序。Event可以是下面的内容:1、throw一个C+抛出的异常(throw为关键字),2、cath一个捕捉到的异常(cath为关键字),3、exec调用系统调用exec时(exec为

16、关键字,目前此功能只在HP-UX下有用)4、fork调用系统调用fork时。(fork为关键字,目前此功能只在-下有用)5、vfrk调用系统调用vfrk时。(vfork为关键字,目前此功能只在HP-UX下有用)6、load或load载入共享库(动态链接库)时。(load为关键字,目前此功能只在HP-UX下有用)7、unload或unload卸载共享库(动态链接库)时。(unload为关键字,目前此功能只在HP-UX下有用)tcatch只设置一次捕捉,当程序停住后,断点被自动删除。三、维护停止点上面说了如何设置程序的停止点,GDB中的停止点也就是上述的三类。在GDB中,如果你觉得已定义好的停止点

17、没有用了,你可以使用delet、clear、disable、enable这几个命令来进程维护。clear清楚所有已定义的停止点。clearclearfilename:function清楚所有设置在函数上的停止点。clearclearfilename:linenum清楚所有设定在指定行上的停止。deltebreakpointsrange 删除指定的断点,breakpoints为断点号。如果不指定断点号,则表示删除所有的断点。range表示断点号的范围(如2-7),其简写命令为d。比删除更好的一种方法是disable停止点,disable了的停止点,GDB不会删除,当你还需要时,enable即可,

18、就好像回收站一样。enablebreakpointsrange enable所指定的停止点,breakpoints为停止号。enablebreakpointsoncerangeenable所指定的停止点一次,当程序停止后,该停止点马上被GDB自动disable。enablebreakpointsdelterangeenable所指定的停止点一次,当程序停止后,该停止点马上被GDB自动删除。四、停止条件维护前面在说到设置断点时,我们提到过可设置一个条件,当条件成立时,程序自动停止,这是一个非常强大的功能,这里,专门说说这个条件相关维护命令。一般来说,为断点设置一个条件,我们使用if关键字,后面跟

19、其断点条件。并且条件设置好后,我们可以用condition命令来修改断点的条件(只有break和watch命令支持if,cath目前暂不支持if)condition修改断点号为bnum的停止条件为expresioncondition清除断点号为bnum的停止条件。还有一个比较特殊的维护命令ignore,可以指定程序运行时,忽略停止条件几次。ignore表示忽略断点号为bnum的停止条件count次。五、为停止点设定运行命令我们可以使用GDB提供的command命令来设置停止点的运行命令。也就是说,当运行的程序在被停止住时,我们可以让你自动运行一些别的命令,这很有利于自动化调试。对给予GDB的自

20、动化调试是一个很强大的支持。commandbnum candlistend为断点号bnum指定一个命令列表。当程序被该断点停住时,gdb会依次运行命令列表中的命令。例如:breakfooifx0commandsprintf“xis%dn”,xcontinueend断点设置在函数foo中,断点条件是x0,如果程序符合条件被停住后,也就是,一旦x的值在foo函数中大于0,GDB会自动打印出x的值,并继续运行程序。如果要清楚断点上的命令序列,那么只要简单的执行以下commands命令,并直接再打个end就行了。六、断点菜单在C+中,可能会出现同一个名字的函数若干次(函数重载),在这种情况下,brea

21、k不能告诉GDB要停在哪个函数的入口。当然,你也可以使用breafunction(type)也就是把函数的参数类型告诉GDB,以指定一个函数。否则的话,GDB会给你列出一个断点菜单供你选择你所需要的断点。你只要输入菜单列表中的编号就可以了。如:(gdb)(gdb)String:after0cancel1al2file:String.cc;lineumber:8673fil:tri.cc;li r:04file:String.cc;lineumber:8755fil:tri.cc;li r:36file:String.cc;lineumber:8467fil:tri.cc;li r:735246

22、Breakpoint1at0xb26c:fileString.cc,line867.rkpit2txb34:fil tri.cc,li 5.Breakpoint3at0xafcc:fileString.cc,line846.Multiplebrekpointswrset.Useth“dlte“comandtodelteunwantedbreakpoints.(gd)(gdb)可见,GDB列出了所有after的重载函数,你可以选以下列表编号就行了。0表示放弃设置断点,1表示所有函数都设置断点。七、恢复程序运行和单步调试当程序被停住后,你可以用continue命令恢复程序的运行直到程序结束,或下一

23、个断点的到来。也可以使用step或next命令单步跟踪程序。contiueignor-countcigor-coutfinre-cont恢复程序运行,直到程序结束,或是下一个断点到来。Ignore-count表示忽略其后的断点次数。contiue,c,fg三个命令都是一样的意思。step单步跟踪,如果有函数调用,他会进入该函数。进入函数的前提是,次函数被编译有debug信息。像VC等工具中的stepin。后面可以加count,也可以不加,不加表示一条一条地执行,加表示执行后面的count条指令,然后再停住。next同样单步跟踪,如果有函数调用,他不会进入函数。想VC等工具中的stepover。

24、后面可以加count,也可以不加。不加表示一条条的执行,加表示执行后面的count指令,然后再停住。setstep-modesetst- on打开step-mde模式,于是,在进行单步跟踪时,程序不会因为没有debug信息而不停住。这个参数很有利于查看机器码。setstep-modeof运行程序,直到当前函数完成返回。并打印函数返回时的堆栈地址和返回值及参数值信息。finish运行程序,直到当前函数完成返回。并打印函数返回时的堆栈地址和返回值及参数值信心。until或u当你厌倦了在一个循环体内单步跟踪时,这个命令可以运行程序知道退出循环体。stepi或sinxti或ni单步跟踪一条机器指令!一

25、条程序代码有可能由数条机器指令完成,stepi和nexti可以单步执行机器指令。与之一样有相同功能的命令式“display/I$c”,当运行完这个命令后,单步跟踪会在打出代码的同时打出机器指令(也就是汇编代码)八、信号(signalssignals)信号是一种软中断,是一种处理异步事件的方法。一般来说,操作系统都支持许多信号。尤其是UNIX,比较重要的应用程序一般都会处理信号。UNIX定义了很多信号,比如SIGINT表示中断字符信号,也就是ctrl+C的信号,SIGBS表示硬件故障的信号,ICHLD表示子进程状态改变信号,SIGKIL表示终止程序运行的信号等等。信号量编程时UNIX下非常重要的

26、一种技术。GDB有能力在你调试程序的时候处理任何一种信号,我们可以告诉GDB需要处理哪一种信号。我们可以要求GDB收到你所指定的信号时,马上停住正在运行的程序,以供你进行调试。你可以用的handle命令来完成这一功能。handle在GDB中定义一个信号处理。信号可以以SIG开头或不以SIG开头,可以用定义一个要处理信号范围(如:SIGIO-SIGKIL,表示处理从IIO信号到SIGKIL的信号,其中包括SIGIO,IIT,IIL三个信号),也可以使用关键字al来表明要处理的所有信号。一旦被调试的程序接收到信号,运行程序马上会被GDB停住,以供调试。其可以是以下几种关键字的一个或多个。nosto

27、p当被调试的程序收到信号时,GDB不会停住程序的运行,但会打出消息告诉你收到这种信号。stop当被调试的程序收到信号时,GDB会停住你的程序。print当被调试的程序收到信号时,GDB会显示出一条信息。noprint当被调试的程序收到信号时,GDB不会告诉你收到信号的信息。pasnoignore当被调试程序收到信号时,GDB不处理信号。这表示,GDB会把这个信号交给调试程序处理。nopasignore当被调试的程序收到信号时,GDB不会让被调试程序来处理这个信号。infosignalsinfohandle查看有哪些信号在被GDB检测中。九、线程(threadthreadstopsstops)如

28、果你的程序时多线程的话,你可以定义你的断点是否在所有的线程上,或是在某个特定的线程。GDB很容易帮你完成这一工作。breakthreadbrealinespecthreathreadnoiflinespec指定了断点是这在源程序的行号。Threadno指定了线程ID,注意,这个ID是GDB分配的,你可以通过“infothreads”命令来查看正在运行程序中的线程信息。如果你不指定thread则表示你的断点设在所有的线程上面。还可以为某个线程指定断点条件,如:(gdb)(gdb)breadkfrik.c:13thread28ifbartablim当程序被GDB停住时,所有的运行线程都会被停住。这

29、方便你查看运行程序的总体情况。而在你恢复程序运行时,所有的线程也会被恢复运行。哪怕是主进程在被单步调试时。查看栈信息当程序被停住了,你需要做的第一件事就是查看程序是在哪里停住了。当你的程序调用了一个函数,函数的地址,函数的参数,函数内的局部变量都会被压入“栈(stack)”中。你可以使用GDB命令来查看当前的栈中的信息。下面是一些查看函数调用栈信息的GDB命令:backtracebt打印当前的函数调用栈的所有信息。如:(gdb)(gdb)t#0func(n=250)atst.c:61x080484inmain(argc=1,argv=0xbff674)atst.c:30#20x49edi_li

30、bc_strt_min()from/lib/lic.so.6从上可以看出函数的调用栈信息:_libc_start_ain-main()-func()backtracet是一个正整数,表示只打印栈顶上n层的栈信息。backtracet-是一个负整数,表示只打印栈底下n层的栈信息。如果你要查看某一层的信息,你需要切换当前的栈,一般来说,程序停止时,最顶层的栈就是当前的栈,如果你要查看栈下面层的详细信息,首先要做的是切换当前栈。framef是一个从0开始的整数,是栈中的层编号。比如:frame0,表示栈顶,frame,表示栈的第二层。up表示向栈的上面移动n层,可以不打n,表示向上移动一层。down

31、那个文件的那一行。函数名filename:funtion那个文件中的那个函数。程序运行时的语句在内存中的地址。二、搜索源代码不仅如此,GDB还提供了源代码搜索的命令:forward-searchserch向前面搜索。revrse-arch全部搜索。其中就是正则表达式,也可以是一个字符串的匹配模式,关于正则表达式,我就不在这里说了,还请各位查看相关资料。三、指定源文件的路径某些时候,用-g编译过后的执行程序中只是包括了源文件的名字,没有路径。GDB提供了可以让你指定源文件的路径的命令,以便GDB进行搜索。directoryir加一个源文件路径到当前路径的前面。如果你要指定多个路径,UNIX下你可

32、以使用“:”,windows下你可以使用“;”。directory清除所有的自定义的源文件搜索路径信息。showdirectories显示定义了的源文件搜索路径。四、源代码的内存可以使用infoline命令来查看源代码在内存中的地址。Infoline后面可以跟“行号”,“函数名”,“文件名:行号”,“文件名:函数名”,这个命令会打印出所指定的源代码在运行时的内存地址,如:(gdb)(gdb)infolinetst.c:funcLine5f“tst.c“startsatdress0x804856andendsat0x80485d.还有一个命令(disassemble)你可以查看源程序测当前执行时

33、的机器码,这个命令会把目前内存中的指令up出来。如下面的示例表示查看函数func的汇编代码。(gdb)(gdb)disassemblefncDumpofasselrcodeforfunctionfunc:0x804850: push%ebpx81fc+1:movsp,%ebp0x804853:movl x0,0xfffc(%ebp)0x80485d:movxfff8(%ebp),%eax0x80487:jlex848700x8048c: ov%esi,esi0x804870:ad%eax,0xfffc(bp)0x804876:jmpx804640x80487b:lea0x0(%esi,1),%

34、esi0x80480: v%edx,%eax0x80485x87fc+5: ov%ebp,%esp0x80489:retEndofssemblerdump.查看运行时数据在你调试程序时,当程序被停住时,可以使用print命令(简写命令为p),或是同义命令inspect来查看当前程序的运行数据。print命令的格式是:printrit/f是表达式,是你所调试的程序的语言的表达式(GDB可以调试多种编程语言),f是输出的格式,比如,如果要把表达式按16进制的格式输出,那么就是/x。一、表达式print和许多GDB的命令一样,可以接受一个表达式,GDB会根据当前的程序运行的数据来计算这个表达式,既然

35、是表达式,那么就可以是当前程序运行中的const常量、变量、函数等内容。可惜的是GDB不能使用你在程序中所定义的宏。表达式的语法应该是当前所调试的语言的语法,由于C/+是一种大众型的语言,所以,本文中的例子都是关于C/+的。(而关于用GDB调试其他语言的章节,将在后面介绍)在表达式中,有几种GDB所支持的操作符,他们可以用在任何一种语言中。是一个数组有关的操作符,在后面会有更详细的说明。:指定一个在文件中或是一个函数中的变量。表示一个指向内存地址的类型为type的一个对象。二、程序变量在GDB中,你可以随时查看以下三种变量的值:1、全局变量(所有文件可见的)2、静态全局变量(当前文件可见的)3

36、、局部变量(当前scope可见的)如果你的局部变量和全局变量发生冲突(也就是重命名),一般情况下是局部变量会隐藏全局变量,也就是说,如果一个全局变量和一个函数重的局部变量同名时,如果当前停止点在函数中,用print显示出的变量的值会是函数中局部变量的值。如果此时你想查看局部变量的值,可以使用“:”操作符。file:variblefunction:varible可以通过这种形式指定你想查看的变量,是哪个文件中的或是哪个函数中的。例如,查看文件f2.c中的全局变量x的值:(gdb)(gdb)pf2.c:x当然,“:”操作符会和C+中的发生冲突,GDB能自动识别“:”是否是C+的操作符,所以不用担心

37、在调试+程序时会出现异常。另外,需要主要的是,如果你的程序编译时开启了优化选项,那么在GDB调试贝优化过的程序时,可能会发生某些变量不能访问,或是取值错误的情况。这个是正常的,因为优化程序会删改你的程序,整理你程序的语句顺序,剔除一些无意义的变量等,所以在GDB调试这种程序时,运行时的指令和你所编写的指令就有不一样的,也就会出现你所想象不到的结果。对付这种情况时,需要在编译程序时关闭编译优化。一般来说,几乎所有的编译器都支持编译优化的开关,例如,GNU的C/+编译器GC,你可以使用“-gstabs”选项来解决这个问题。关于编译器的参数,还请查看编译器的使用说明文档。三、数组有时候,你需要查看一

38、段连续的内存空间的值。比如数组的一段,或是动态分配的数据的大小。你可以使用GDB的“”操作符,“”的左边是第一个内存的地址的值,“”的右边则是你想查看的内存的长度。例如,你的程序中有这样的语句:int*ary=(int*)maloc(len*sizeof(int)于是,在GDB调试过程中,你可以用如下命令显示出这个动态数组的取值:p*arylen的左边是数组的首地址的值,也就是变量ary所指向的内容,右边则是数据的长度,其保存在变量len中,其输出结果,大约是下面这个样子:(gdb)(gdb)p*arylen$1=2,4,6,8,10,12,14,16,18,20,2,24,26,28,30,

39、32,34,36,38,40如果是静态数组的话,可以直接用print数组名,就可以显示数组中所有数据的内容了。四、输出格式一般来说,GDB会根据变量的类型输出变量的值。但你也可以自定义GDB的输出格式。例如,你想输出一个整数的十六进制,或是二进制来查看这个整形变量的位的情况。要做到这样,你可以使用GDB的数据显示格式:x按十六进制格式显示变量。d按十进制格式显示变量。u按十六进制格式显示无符号整型。o按八进制格式显示变量。t按二进制格式显示变量。a按十六进制格式显示变量。c按字符格式显示变量。f按浮点数格式显示变量。(gdb)(gdb)pi$21=10(gdb)(gdb)p/ai$2=0x65

40、(gdb)(gdb)p/ci$23=10e(gdb)(gdb)p/fi$24=1.453145e-43(gdb)(gdb)p/xi$25=0x65(gdb)(gdb)p/ti$26=1010五、查看内存你可以使用examine命令(简写是x)来查看内存地址中的值。X命令的语法如下所示:x/、f、是可选参数。n是一个正整数,表示显示内存的长度,也就是说从当前地址向后显示几个地址的内容。f表示显示格式,参加上面。如果地址所指的是字符串,那么格式是s,如果地址是指令地址,那么格式也可以是i。u表示从当前的地址往后请求的字节数,如果不指定的话,GDB默认是4个bytes。u参数可以用下面的字符来代替,

41、b表示单字节,h表示双字节,w表示四字节,g表示八字节。当我们指定了字节长度后,GDB会从指定的内存地址开始,读写指定字节,并把其当作一个值取出来。表示一个内存地址。n/fu三个参数可以一起使用。例如:命令:x/3uh0x54320表示,从内存地址0x54320读取内容,h表示以双字节为一个单位,3表示三个单位,u表示按十六进制显示。六、自动显示你可以设置一些自动显示的变量,当程序停住时,或是在你单步跟踪时,这些变量会自动显示。相关的GDB命令是display。displayisplyfmtdisplay/adrexpr是一个表达式,fmt表示显示的格式,adr表示内存地址,当你用displa

42、y设定好了一个或多个表达式后,只要你的程序被停下来,GDB会自动显示你所设置的这些表达式的值。格式i和s同样被display支持,一个非常有用的命令是:display/i$pc$pc是GDB的环境变量,表示着指令的地址,/i则表示输出格式为机器指令码,也就是汇编。于是当程序停下来后,就会出现源代码和机器指令码相对应的情形,这是一个很有意思的功能。下面是一些和display相关的GDB命令:undisplayeltedisplay删除自动显示,ms意为所设置好了的自动显示的编号。如果要同时删除几个,编号可以用空格分隔,如果要删除一个范围内的编号,可以用减号表示(如:2-5)disabledisp

43、layenal isplysdisable和enalbe不删除自动显示的设置,而只是让其失效和恢复。infodisplay查看display设置的自动显示的信息。GDB会打印出一张表格,向你报告调试中设置了多少个自动显示设置,其中包括,设置的编号,表达式,是否enable。七、设置显示选项GDB中关于显示的选项比较多,这里只举大多数常用的选项。setprintadressstrit rsson打开地址输出,当程序显示函数信息时,GDB会显示出函数的参数地址。系统默认为打开的,如:(gdb)(gdb)f#0set_quotes(lq=0x34c78“)atinpt.c:530530if(lquo

44、te!=def_lquote)setprintadressof关闭函数的参数地址显示,如:(gdb)(gdb)setprintadrof(gd)(gd)f#0set_quotes(lq=“)atinput.c:53053if(luote!def_luote)showprintadress查看当前地址显示选项是否打开。setprintarystritryon打开数组显示,打开后当数组显示时,每个元素占一行,如果不打开的话,每个元素则以逗号分隔。这个选项默认是关闭的。与之相关的两个命令如下,就不多说了。setprintaryofshowprintarysetritelments这个选项主要是设置数

45、组的,如果你的数组太大了,那么就可以指定一个来指定数据显示的最大长度,当到达这个长度时,GDB就不再往下显示了,如果设置为0,则表示不限制。showprintelments查看ritl ts的选项信息。setprintul-stop如果打开了这个选项,那么当显示字符串时,遇到结束符则停止显示。这个选项默认为of。setprintpretyon如果打开ritfprety这个选项,那么当GDB显示结构体时会比较漂亮。如:$1=next=0x0,flagsswet=1,sour,meat=0x54“Pork“setprintpretyof关闭rintfprety这个选项,GDB显示结构体时会如下显示

46、:$1=ext=0x0,flags=swet=1,sour=1,meat=0x54“Pork“showprintprety查看GDB时如何显示结构体的。setprintsevenbit-strings设置字符显示,是否按“”的格式显示,如果打开,则字符串或字符数据按n显示,如“065”。showprintsevenbit-strings查看字符显示开关是否打开。setprintunio设置显示结构体时,是否显式其内的联合体数据。例如有以下数据结构:typedfenumTre,BugSpecis;tyf Big_tre,Acorn,SedlingTre_forms;typedfenumCatrp

47、ilar,Cocoon,ButerflyBug_fors;structthingSpecisit;unioTre_frmstre;Bugforsbug;form;structthingfo=Tre,Acorn;当打开这个开关时,执行pfo命令后,会如下显示:$1=it=Tre,form=tre=Acorn,bug=Cocoon当关闭这个开关时,执行pfo命令后,会如下显示:$1=it=Tre,form=.showprintunio查看联合体数据的显示方式。setprintobject在C+中,如果一个对象指针所指向其派生类,如果打开这个选项,GDB会自动按照虚方法条用的规则显示输出,如果关闭这

48、两个选项的话,GDB就不管虚函数表了。这个选项默认是of。showprintobject查看对象选项的设置。setprintstatic-mebers这个选项表示,当显示一个C+对象中的内容时,是否显示其中的静态数据成员。默认是on。showprintstatic-mebers查看静态数据成员选项设置。setprintvtbl当此选项打开时,GDB将用比较规整的格式来显示虚函数。其默认是关闭的。showprintvtbl查看虚函数显示格式的选项。八、历史记录当你的用GDB的print查看程序运行的数据时,你每一个print都会被GDB记录一下。GDB会以$1、$2、$3这样的方式为你每一个pr

49、int命令编上号。于是,你可以使用这个编号访问以前的表达式,如$1。这个功能所带来的好处是,如果你先前输入了一个比较长的表达式,如果你还想查看这个表达式的值,你可以使用历史记录来访问,省去了重复输入。九、GDBGDB环境变量你可以在的调试环境中定义自己的变量,用来保存一些调试程序中的运行数据。要定义一个GDB的变量很简单。使用GDB的set命令。GDB的环境变量和UNIX一样,也是以$起头。如:setfo=*object_ptr使用环境变量时,GDB会在你第一次使用时创建这个变量,而在以后的使用中,则直接对其赋值。环境变量没有类型,你可以给环境变量定义任一的类型。包括结构体和数组。showconvenice该命令查看当前所设置的所有的环境变量。这时一个比较强大的功能,环境变量和程序变量的交互使用,将使得程序调试更为灵活便捷。例如:set$i=0printbar$i+-contets于是,当你就不必printbar0-contets,printbar1-contets地输入命令了。输入这样的命令后,只用敲回车,重复执行上一条语

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 实用文档 > 简明教程

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报