使用GDB一般来说GDB主要调试的是C/C++的程序。要调试C/C++的程序,首先在编译时,我们必须要把调试信息加到可执行文件中。使用编译器(cc/gcc/g++)的-g参数可以做到这一点。如:cc-ghello.c-ohellog++-ghello.cpp-ohello如果没有-g,你将看不见程序的函数名、变量名,所代替的全是运行时的内存地址。当你用-g把调试信息加入之后,并成功编译目标代码以后,让我们来看看如何用gdb来调试他。进入GDB启动GDB的方法有以下几种:1、gdbprogramprogram也就是你的执行文件,一般在当然目录下。2、gdbprogramcore用gdb同时调试一个运行程序和core文件,core是程序非法执行后coredump后产生的文件。3、gdbpid如果你的程序是一个服务程序,那么你可以指定这个服务程序运行时的进程ID。gdb会自动attach上去,并调试他。program应该在PATH环境变量中搜索得到。GDB启动时,可以加上一些GDB的启动开关,详细的开关可以用gdb-help查看。我在下面只例举一些比较常用的参数:参数说明-symbols[file](-s)读取文件中的符号表-exec[file](-e)调试一个可执行文件-se[file]上二者的缩写-core[file](-c)读入一个coredump文件-pidnumber(-p)启动attach模式,除错一个执行中的行程。number是目标行程的pid-directory[directory](-d)将directory加入原始码的搜寻路行-readnow(-r)一次读取完所有的符号表,这会让启动gdb的时间变长,但在执行往后的除错动作会较快速。下列还有部分选择性的参数,我列出几个目前用的到的:-quiet-silent-q安静模式,启动时gdb将不会显示版权页。-windows-w与下一选项相反,这会启动GUI-nowindows-nw如果gdb有编入GUI的话,这个选项会关掉它。-cd[directory]切换工作目录为directory而不是现在的目录-tty[device](-t)指定device为程式的标准输出入--args这个参数要当作命令列的最后一个参数,其后跟随的参数都会被视为「欲传给将调试的程序的参数」当然我们也不一定要在启动时指定调试来源。file指令可以指定要调试的程序,功能就与-se一样,其实这样指定是比较方便的。在执行程序前,我们可以先指定命令列参数,如同--args参数的效果。程序运行参数setargs指定运行时的命令列参数showargs查看现在的命令列参数是什么。由于gdb调试的对象是已经编译好的可执行文件,所以这里我们不必像VS.NET一样等半天。有一点必须注意,gdb传给程序的命令列参数是程序开始执行前的那一份命令列参数,如果程序已经开始执行,就算用中断点中断执行然后改变命令列参数,也只会在下一次执行时变更才会生效。运行环境path设定程序的运行路径。showpaths查看程序的运行路径。setenvironmentvarname[=value]设置环境变量,如setenvUSR=showenvironment[varname]查看环境变量。工作目录cd相当于shell的cd命令。Pwd显示当前的所在目录。程序的输入输出infoterminal显示你程序用到的终端的模式。使用重定向控制程序的输出。如:runoutfiletty命令可以指定写输入输出的终端设备。如:tty/dev/ttyb调试已运行的程序两种方法:1、在UNIX下用ps查看正在运行的程序的PID(进程ID),然后用gdbPID格式挂接正在运行的程序。2、先用gdb关联上源代码,并进行gdb,在gdb中用attach命令来挂接进程的PID。并用detach来取消挂接的进程。暂停/恢复程序运行我们在调试的过程中,会推测某些代码是否出了问题,如果要测试该段代码,可以让程序执行到那区段前暂停,然后我们来测试看看是出了什么问题。一、设置断点(BreakPoint)参数说明break[function]在某函数的进入点设中断点。C++中可以使用class::function或function(type,type)格式来指定函数名。break+offset|-offset当程序停止时,在停止位置的前/后第offset行设中断点breaklinenum指定行号设中断点breakfilename:linenum在某sourcefile的第几行或指定函数设定中断点break在下一个要执行的指令设中断点break[args]if[cond]当[cond]这个运算式为真,设定中断点。args可能是上列的任一种情形。tbreakargs只会生效一次的中断点rbreakregex使用正则运算来找寻可能的函数,并在其进入点设中断点。EX:(gdb)rbreak.这样每个函数开头都有中断点了。Thesyntaxoftheregularexpressionisthestandardoneusedwithtoolslike`grep'.Notethatthisisdifferentfromthesyntaxusedbyshells,soforinstancefoo*matchesallfunctionsthatincludeanfofollowedbyzeroormoreos.Thereisanimplicit.*leadingandtrailingtheregularexpressionyousupply,sotomatchonlyfunctionsthatbeginwithfoo,use^foo.WhendebuggingC++programs,rbreakisusefulforsettingbreakpointsonoverloadedfunctionsthatarenotmembersofanyspecialclasses.break*address在程序运行的内存地址设置断点breakfilename:functioninfobreak[n]查看断点,n表示断点号值得一提的是,C++允许overloading,所以直接指定函数名称有时候gdb无法辨认要把中断点设在哪。举例:inttakeout(inti,intj){...}inttakeout(floati,floatj){...}这时候我们可以设定breaktakeout(int,int),这样就会在上面的函数的进入点设定中断点。当然假如我们只输入breaktakeout,gdb会显示一个互动示选单显示所有可能的函式的原型,让我们挑选要将中断点设在哪个函式。break的简写是b,通常只输入简写方便多了。二、设置观察点(WatchPoint)观察点一般来观察某个表达式(变量也是一种表达式)的值是否有变化了,如果有变化,马上停住程序。我们有下面的几种方法来设置观察点:watchexpr为表达式(变量)expr设置一个观察点。一量表达式值有变化时,马上停住程序。rwatchexpr当表达式(变量)expr被读时,停住程序。awatchexpr当表达式(变量)的值被读或被写时,停住程序。infowatchpoints列出当前所设置了的所有观察点。三、设置捕捉点(CatchPoint)你可设置捕捉点来补捉程序运行时的一些事件。如:载入共享库(动态链接库)或是C++的异常。设置捕捉点的格式为:catchevent当event发生时,停住程序。event可以是下面的内容:1、throw一个C++抛出的异常。(throw为关键字)2、catch一个C++捕捉到的异常。(catch为关键字)3、exec调用系统调用exec时。(exec为关键字,目前此功能只在HP-UX下有用)4、fork调用系统调用fork时。(fork为关键字,目前此功能只在HP-UX下有用)5、vfork调用系统调用vfork时。(vfork为关键字,目前此功能只在HP-UX下有用)6、load或load载入共享库(动态链接库)时。(load为关键字,目前此功能只在HP-UX下有用)7、unload或unload卸载共享库(动态链接库)时。(unload为关键字,目前此功能只在HP-UX下有用)tcatchevent只设置一次捕捉点,当程序停住以后,应点被自动删除。使用infobreak命令列出当前捕捉点。四、维护停止点上面说了如何设置程序的停止点,GDB中的停止点也就是上述的三类。在GDB中,如果你觉得已定义好的停止点没有用了,你可以使用delete、clear、disable、enable这几个命令来进行维护。clear清除停止点,后面跟(文件名)行号或函数名,未指定则表示清除所有断点比删除更好的一种方法是disable停止点,disable了的停止点,GDB不会删除,当你还需要时,enable即可,就好像回收站一样。disable[breakpoints][range...]disable所指定的停止点,breakpoints为停止点号。如果什么都不指定,表示disable所有的停止点。简写命令是dis.enable[breakpoints][range...]enable所指定的停止点,breakpoints为停止点号。enable[breakpoints]oncerange...enable所指定的停止点一次,当程序停止后,该停止点马上被GDB自动disable。enable[breakpoints]deleterange...enable所指定的停止点一次,当程序停止后,该停止点马上被GDB自动删除。五、停止条件维护前面在说到设置断点时,我们提到过可以设置一个条件,当条件成立时,程序自动停止,这是一个非常强大的功能,这里,我想专门说说这个条件的相关维护命令。一般来说,为断点设置一个条件,我们使用if关键词,后面跟其断点条件。并且,条件设置好后,我们可以用condition命令来修改断点的条件。(只有break和watch命令支持if,catch目前暂不支持if)conditionbnumexpression修改断点号为bnum的停止条件为expression。conditionbnum清除断点号为bnum的停止条件。还有一个比较特殊的维护命令ignore,你可以指定程序运行时,忽略停止条件几次。ignorebnumcount表示忽略断点号为bnum的停止条件count次。六、为停止点设定运行命令我们可以使用GDB提供的command命令来设置停止点的运行命令。也就是说,当运行的程序在被停止住时,我们可以让其自动运行一些别的命令,这很有利行自动化调试。对基于GDB的自动化调试是一个强大的支持。commands[bnum]...command-list...end为断点号bnum指写一个命令列表。当程序被该断点停住时,gdb会依次运行命令列表中的命令。例如:breakfooifx0commandsprintfxis%d\n,xcontinueend断点设置在函数foo中,断点条件是x0,如果程序被断住后,也就是,一旦x的值在foo函数中大于0,GDB会自动打印出x的值,并继续运行程序。如果你要清除断点上的命令序列,那么只要简单的执行一下commands命令,并直接在打个end就行了。七、断点菜单在C++中,可能会重复出现同一个名字的函数若干次(函数重载),在这种情况下,break不能告诉GDB要停在哪个函数的入口。当然,你可以使用break也就是把函数的参数类型告诉GDB,以指定一个函数。否则的话,GDB会给你列出一个断点菜单供你选择你所需要的断点。你只要输入你菜单列表中的编号就可以了。如:(gdb)bString::after[0]cancel[1]all[2]file:String.cc;linenumber:867[3]file:String.cc;linenumber:860[4]file:Strin