




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、gdb调试调试命令:gdb 【可执行文件】退出gdb:quit(q)(在gdb中大部分命令都可以用缩写表示)显示源代码:list (l)查看某行代码:list 【行号n】 (缩写l 行号n)程序会显示n行上下共十行的代码查看函数代码:list 【函数名】 (缩写 l 函数名)显示当前行后面的代码:list显示当前行前面的代码:list 一般是显示当前行的上5行和下5行,或者显示当前行的上2行和下8行,默认共显示10行。也可以自己设置显示的范围。set listsize : 设置一次显示源代码的行数show listsize:查看当前listsize的设置。显示first到last行之间的代码:
2、list ,显示从前行到last行的代码:list ,向后显示源代码:list +设置断点:break 【行号n】(缩写b 行号n)break 【函数名】 (缩写b 函数名)break if 条件成立时停止查看断点:info break (缩写 i b)断点都有断点号单步跟踪并进入函数:step (s)单步跟踪,但不进入函数:next (n)运行到下一断点:continue (c)不设置断点,直接运行程序:run (r)finish:运行程序,知道当前函数完成返回,并打印函数返回时的堆栈地址及参数值等信息跳出循环: until查看变量值:print 【变量名】(p 变量名)delete 【断点
3、号】:删除断点clear命令:clear命令是用来清除断点的的命令clear 要清楚的断点所在的行号clear命令与delete命令不同,delete命令后跟断点编号,而clear命令后面跟的是断点所在的行号,另外,使用clear命令,gdb会给出提示,而delete命令没有。enable命令:enable可以恢复暂时失效的断点enable 断点标号要恢复多个断点时,可用空格将断点编号隔开disable命令:disable命令可是刚设置的的断点失效,失效后用命令cont继续程序的执行disable 断点编号ptype 【变量名】:查看变量类型print 数组名标号:查看数组元素的值print
4、【变量1】=n:将变量1的值改为nprint 命令详解:形式1:print 表达式表达式中与两种特殊符号要注意,$,$,用print查看表达式时,表达式的值都会被记录下来,并会以$1,$2,$3等编上号,这样就可以通过print $n,命令查看系统记录的 $n的值,而要查看从当前记录的值开始往后推n个的记录值时应该用$符号,如现在记录到$5,要看看$3,则可用print $2命令查看。另外如果$后边不加数字,相当于print当前标号之前的print值,同时,如果$加不加数字,则表示print当前标号倒数的第二个print记录。形式2:print 变量=表达式形式3:打印内存某个部分开始的一块连
5、续空间的内容Print 开始表达式要打印内存空间的大小开始表达式应该是内存中的一个表达式,他的输入结果以数组的形式,其中第0个元素师开始表达式的值,第1个元素是在内存中紧挨着开始表达式的空间中存放的值,以此类推。display命令:display用来显示一些表达式的值,使用该命令后,每当程序运行到断点处就会显示该表达式的值,可以用它来观察一些表达式的值,它与print的区别是,display命令每次调试中断程序,挂起指令都要显示变量的值。形式:display 要显示值的表达式set 命令:set除了可以显示数据外,还可以修改变量的值使用观察窗口使用观察窗口与在程序的特定位置设置断点实现的功能相
6、似,但使用观察窗口值在表达式为真时中断程序的运行。watch命令:使用watch命令设置观察窗口例如程序段如下:for(counter=0;counter15则程序会在表达式counter15为真时中断程序搜索源代码向前搜索:forward-search 或search 反向搜索:reverse-search 其中就是正则表达式,也是一个字符串的匹配模式在输入gdb命令时,直接点击回车,执行上条命令编译错误:编译程序时没有符合语法规范导致编译错误运行错误:编译器检查不出这种错误,但在运行时可能会出现这种错误逻辑错误:编译和运行都很顺利,但是程序没有干他该干的事段错误:由于访问非法地址发生的错误
7、访问系统数据区,尤其是往系统保护的内存地址写数据,最常见的是一个内存以0地址内存越界(数组越界,数据类型不一致等),访问不到属于你的内存区域 。查看栈信息当程序被停止的时候,需要做的第一件事是查看程序是在哪里停止的。当程序调用了一个函数时,函数的地址,函数的参数,函数内部的局部变量都会被压入“栈”(stack)中,栈是内存中的一段连续空间。查看栈信息命令1:backtrace 或者bt例如:(gdb)bt#0 func (n=250) at tst.c:6#1 0x08048524 in main (argc=1,argv=0xbffff674) at tst.c:30#2 0x400409e
8、d in _libc_start_main () from /lib/lib/libc.so.6从中可以看出函数的调用栈信息: _libc_start_main 到main()到func(),因为栈是后进先出,一次输出的栈信息和函数调用顺序刚好相反。命令2:Backtrace 或者bt 其中n是一个正整数,表示只打印栈顶上n层的栈信息。命令3:backtrace 或者bt -n是个负整数,表示只打印栈底下你层的栈信息。命令4:frame 或者 f 其中n是一个从零开始的整数,是栈中的层编号。frame 0表示栈顶,frame 1表示栈的第二层。命令5:up 表示向栈底移动n层,不输入n,表示想
9、栈底方向移动一层。因为栈底在内存的高地址区域,栈顶处于低地址区域,所以命令用up,反之用down。命令6:down 表示向栈顶方向移动n层命令7:frame 或者f产看当前栈的信息显示的信息包括:栈的层编号,当前的函数名,函数的参数值,函数所在文件及行号,函数执行到的语句。命令8:info frame 或者info f该命令会显示出更加详细的当前栈层的信息,只不过大多数都是运行时的内地址。命令9:Info args显示出当前函数的参数及值。命令10:Info locals显示出当前函数的参数名及值。命令11:info catch显示出当前函数中的异常处理信息。Linux core dump详解
10、有的程序可以通过编译,但在运行时会出现Segment fault(段错误).这通常都是指针错误引起的.以下是我们详细的对Linux core dump的调试技术进行的介绍:1.Linux core dump前言:有的程序可以通过编译,但在运行时会出现Segment fault(段错误).这通常都是指针错误引起的.但这不像编译错误一样会提示到文件-行,而是没有任何信息,使得我们的调试变得困难起来.2. Linux core dump gdb:有一种办法是,我们用gdb的step,一步一步寻找.这放在短小的代码中是可行的,但要让你step一个上万行的代码,我想你会从此厌恶程序员这个名字,而把他叫做
11、调试员.我们还有更好的办法,这就是core file.3. Linux core dump ulimit:如果想让系统在信号中断造成的错误时产生core文件,我们需要在shell中按如下设置:#设置core大小为无限ulimit -c unlimited#设置文件大小为无限ulimit unlimited这些需要有root权限,在ubuntu下每次重新打开中断都需要重新输入上面的第一条命令,来设置core大小为无限.4. Linux core dump用gdb查看core文件:下面我们可以在发生运行时信号引起的错误时发生core dump了.发生core dump之后,用gdb进行查看core
12、文件的内容,以定位文件中引发core dump的行.gdb exec file core file如:gdb ./test test.core在进入gdb后,用bt命令查看backtrace以检查发生程序运行到哪里,来定位core dump的文件-行.5.要怎麽才不会让core文件出现?如果用的是tcsh的话,以试著在.tcshrc里加一行:limit coredumpsize 0如果用的是bash的话,在/etc/profile里加上(或者修改)一条:ulimit -c 06.何谓Linux core dump?我们在开发(或使用)一个程序时,最怕的就是程序莫明其妙地当掉。虽然系统没事,但我
13、们下次仍可能遇到相同的问题。于是这时操作系统就会把程序当掉时的内存内容dump出来,让我们或是debugger做为参考。这个动作就叫作core dump。7.有一招,可以让你看出core最好用的地方gdb -c core进去后打where,就可以show出你是在程序哪一行当掉的,还有在当掉时在哪个function里,这个function是被哪个function所call的,而这个function又是被哪个function所call的.一直到main()由这个信息,可以找出五六成的bug.屡试不爽,但先决条件,当你在compile时必须把debug information的选项打开不然,就会出现
14、一大堆你看不懂的东西,而不是你喜欢的源程序。8.System Dump和Core Dump的区别许多没有做过UNIX系统级软件开发的人士,可能只听说过Dump,而并不知道系统Dump和Core Dump的区别,甚至混为一谈。1)系统Dump(System Dump)所有开放式操作系统,都存在系统DUMP问题。产生原因:由于系统关键/核心进程,产生严重的无法恢复的错误,为了避免系统相关资源受到更大损害,操作系统都会强行停止运行,并将当前内存中的各种结构,核心进程出错位置及其代码状态,保存下来,以便以后分析。最常见的原因是指令走飞,或者缓冲区溢出,或者内存访问越界。走飞就是说代码流有问题,导致执行
15、到某一步指令混乱,跳转到一些不属于它的指令位置去执行一些莫名其妙的东西(没人知道那些地方本来是代码还是数据,而且是不是正确的代码开始位置),或者调用到不属于此进程的内存空间。写过C程序及汇编程序的人士,对这些现象应当是很清楚的。系统DUMP生成过程的特点:在生成DUMP过程中,为了避免过多的操作结构,导致问题所在位置正好也在生成DUMP过程所涉及的资源中,造成DUMP不能正常生成,操作系统都用尽量简单的代码来完成,所以避开了一切复杂的管理结构,如文件系统)LVM等等,所以这就是为什么几乎所有开放系统,都要求DUMP设备空间是物理连续的不用定位一个个数据块,从DUMP设备开头一直写直到完成,这个
16、过程可以只用BIOS级别的操作就可以。这也是为什么在企业级UNIX普遍使用LVM的现状下,DUMP设备只可能是裸设备而不可能是文件系统文件,而且b只/b用作DUMP的设备,做LVM镜像是无用的系统此时根本没有LVM操作,它不会管什么镜像不镜像,就用第一份连续写下去。所以UNIX系统也不例外,它会将DUMP写到一个裸设或磁带设备。在重启的时候,如果设置的DUMP转存目录(文件系统中的目录)有足够空间,它将会转存成一个文件系统文件,缺省情况下,b对于AIX来说是/var/adm/ras/下的vmcore*这样的文件,对于HPUX来说是/var/adm/crash下的目录及文件。/b当然,也可以选择
17、将其转存到磁带设备。会造成系统DUMP的原因主要是:系统补丁级别不一致或缺少)系统内核扩展有BUG(例如Oracle就会安装系统内核扩展)驱动程序有BUG(因为设备驱动程序一般是工作在内核级别的),等等。所以一旦经常发生类似的系统DUMP,可以考虑将系统补丁包打到最新并一致化)升级微码)升级设备驱动程序(包括FC多路冗余软件)升级安装了内核扩展的软件的补丁包等等。2)进程Core Dump进程Core Dump产生的技术原因,基本等同于系统DUMP,就是说从程序原理上来说是基本一致的。但进程是运行在低一级的优先级上(此优先级不同于系统中对进程定义的优先级,而是指CPU代码指令的优先级),被操作
18、系统所控制,所以操作系统可以在一个进程出问题时,不影响其他进程的情况下,中止此进程的运行,并将相关环境保存下来,这就是core dump文件,可供分析。如果进程是用高级语言编写并编译的,且用户有源程序,那么可以通过在编译时带上诊断用符号表(所有高级语言编译程序都有这种功能),通过系统提供的分析工具,加上core文件,能够分析到哪一个源程序语句造成的问题,进而比较容易地修正问题,当然,要做到这样,除非一开始就带上了符号表进行编译,否则只能重新编译程序,并重新运行程序,重现错误,才能显示出源程序出错位置。如果用户没有源程序,那么只能分析到汇编指令的级别,难于查找问题所在并作出修正,所以这种情况下就
19、不必多费心了,找到出问题的地方也没有办法。进程Core Dump的时候,操作系统会将进程异常终止掉并释放其占用的资源,不可能对系统本身的运行造成危害。这是与系统DUMP根本区别的一点,系统DUMP产生时,一定伴随着系统崩溃和停机,进程Core Dump时,只会造成相应的进程被终止,系统本身不可能崩溃。当然如果此进程与其他进程有关联,其他进程也会受到影响,至于后果是什么,就看相关进程对这种异常情况(与自己相关的进程突然终止)的处理机制是什么了,没有一概的定论。9.关于coredump文件的其它说明:1)如何生成coredump文件?登陆LINUX服务器,任意位置键入echo ulimit -c
20、1024 /etc/profile退出LINUX重新登陆LINUX键入ulimit -c如果显示1024那么说明coredump已经被开启。2). core文件的简单介绍在一个程序崩溃时,它一般会在指定目录下生成一个core文件。core文件仅仅是一个内存映象(同时加上调试信息),主要是用来调试的。3).开启或关闭core文件的生成用以下命令来阻止系统生成core文件:ulimit -c 0下面的命令可以检查生成core文件的选项是否打开:ulimit -a该命令将显示所有的用户定制,其中选项-a代表“all”。也可以修改系统文件来调整core选项在/etc/profile通常会有这样一句话来
21、禁止产生core文件,通常这种设置是合理的:# No core files by defaultulimit -S -c 0 /dev/null 2&1但是在开发过程中有时为了调试问题,还是需要在特定的用户环境下打开core文件产生的设置。在用户的/.bash_profile里加上ulimit -c unlimited来让特定的用户可以产生core文件。如果ulimit -c 0则也是禁止产生core文件,而ulimit -c 1024则限制产生的core文件的大小不能超过1024kb4).设置Core Dump的核心转储文件目录和命名规则/proc/sys/kernel/core_uses_
22、pid可以控制产生的core文件的文件名中是否添加pid作为扩展,如果添加则文件内容为1,否则为0proc/sys/kernel/core_pattern可以设置格式化的core文件保存位置或文件名,比如原来文件内容是core-%e可以这样修改:echo /corefile/core-%e-%p-%t core_pattern将会控制所产生的core文件会存放到/corefile目录下,产生的文件名为core-命令名-pid-时间戳以下是参数列表:%p - insert pid into filename添加pid%u - insert current uid into filename添加当
23、前uid%g - insert current gid into filename添加当前gid%s - insert signal that caused the coredump into the filename添加导致产生core的信号%t - insert UNIX time that the coredump occurred into filename添加core文件生成时的unix时间%h - insert hostname where the coredump happened into filename添加主机名%e - insert coredumping executa
24、ble name into filename添加命令名5).使用core文件在core文件所在目录下键入:gdb -c core它会启动GNU的调试器,来调试core文件,并且会显示生成此core文件的程序名,中止此程序的信号等等。如果你已经知道是由什么程序生成此core文件的,比如MyServer崩溃了生成core.12345,那么用此指令调试:gdb -c core MyServer6).一个小方法来测试产生core文件直接输入指令:kill -s SIGSEGV $core详解2Core,又称之为Core Dump文件,是Unix/Linux操作系统的一种机制,对于线上服务而言,Core
25、令人闻之色变,因为出Core的过程意味着服务暂时不能正常响应,需要恢复,并且随着吐Core进程的内存空间越大,此过程可能持续很长一段时间(例如当进程占用60G+以上内存时,完整Core文件需要15分钟才能完全写到磁盘上),这期间产生的流量损失,不可估量。凡事皆有两面性,OS在出Core的同时,虽然会终止掉当前进程,但是也会保留下第一手的现场数据,OS仿佛是一架被按下快门的相机,而照片就是产出的Core文件。里面含有当进程被终止时内存、CPU寄存器等信息,可以供后续开发人员进行调试。关于Core产生的原因很多,比如过去一些Unix的版本不支持现代Linux上这种GDB直接附着到进程上进行调试的机
26、制,需要先向进程发送终止信号,然后用工具阅读core文件。在Linux上,我们就可以使用kill向一个指定的进程发送信号或者使用gcore命令来使其主动出Core并退出。如果从浅层次的原因上来讲,出Core意味着当前进程存在BUG,需要程序员修复。从深层次的原因上讲,是当前进程触犯了某些OS层级的保护机制,逼迫OS向当前进程发送诸如SIGSEGV(即signal 11)之类的信号, 例如访问空指针或数组越界出Core,实际上是触犯了OS的内存管理,访问了非当前进程的内存空间,OS需要通过出Core来进行警示,这就好像一个人身体内存在病毒,免疫系统就会通过发热来警示,并导致人体发烧是一个道理(有
27、意思的是,并不是每次数组越界都会出Core,这和OS的内存管理中虚拟页面分配大小和边界有关,即使不出Core,也很有可能读到脏数据,引起后续程序行为紊乱,这是一种很难追查的BUG)。说了这些,似乎感觉Core很强势,让人感觉缺乏控制力,其实不然。控制Core产生的行为和方式,有两个途径:1.修改/proc/sys/kernel/core_pattern文件,此文件用于控制Core文件产生的文件名,默认情况下,此文件内容只有一行内容:“core”,此文件支持定制,一般使用%配合不同的字符,这里罗列几种:%p 出Core进程的PID%u 出Core进程的UID%s 造成Core的signal号%t
28、 出Core的时间,从1970-01-0100:00:00开始的秒数%e 出Core进程对应的可执行文件名2.Ulimit C命令,此命令可以显示当前OS对于Core文件大小的限制,如果为0,则表示不允许产生Core文件。如果想进行修改,可以使用:Ulimit c n其中n为数字,表示允许Core文件体积的最大值,单位为Kb,如果想设为无限大,可以执行:Ulimit c unlimited产生了Core文件之后,就是如何查看Core文件,并确定问题所在,进行修复。为此,我们不妨先来看看Core文件的格式,多了解一些Core文件。首先可以明确一点,Core文件的格式ELF格式,这一点可以通过使用
29、readelf -h命令来证实,如下图:从读出来的ELF头信息可以看到,此文件类型为Core文件,那么readelf是如何得知的呢?可以从下面的数据结构中窥得一二:其中当值为4的时候,表示当前文件为Core文件。如此,整个过程就很清楚了。了解了这些之后,我们来看看如何阅读Core文件,并从中追查BUG。在Linux下,一般读取Core的命令为:gdb exec_file core_file使用GDB,先从可执行文件中读取符号表信息,然后读取Core文件。如果不与可执行文件搅合在一起可以吗?答案是不行,因为Core文件中没有符号表信息,无法进行调试,可以使用如下命令来验证:Objdump x c
30、ore_file | tail我们看到如下两行信息:SYMBOL TABLE:no symbols表明当前的ELF格式文件中没有符号表信息。为了解释如何看Core中信息,我们来举一个简单的例子:#include “stdio.h”int main()int stack_of100000000;int b=1;int* a;*a=b;这段程序使用gcc g a.c o a进行编译,运行后直接会Core掉,使用gdb a core_file查看栈信息,可见其Core在了这行代码:int stack_of100000000;原因很明显,直接在栈上申请如此大的数组,导致栈空间溢出,触犯了OS对于栈空间
31、大小的限制,所以出Core(这里是否出Core还和OS对栈空间的大小配置有关,一般为8M)。但是这里要明确一点,真正出Core的代码不是分配栈空间的int stack_of100000000, 而是后面这句int b=1, 为何?出Core的一种原因是因为对内存的非法访问,在上面的代码中分配数组stack_of时并未访问它,但是在其后声明变量并赋值,就相当于进行了越界访问,继而出Core。为了解释得更详细些,让我们使用gdb来看一下出Core的地方,使用命令gdb a core_file可见:可知程序出现了段错误“Segmentation fault”, 代码是int b=1这句。我们来查看一
32、下当前的栈信息:其中可见指令指针rip指向地址为0400473, 我们来看下当前的指令是什么:这条movl指令要把立即数1送到0xffffffffe8287bfc(%rbp)这个地址去,其中rbp存储的是帧指针,而0xffffffffe8287bfc很明显是一个负数,结果计算为-400000004。这就可以解释了:其中我们申请的int stack_of100000000占用400000000字节,b是int类型,占用4个字节,且栈空间是由高地址向低地址延伸,那么b的栈地址就是0xffffffffe8287bfc(%rbp),也就是$rbp-400000004。当我们尝试访问此地址时:可以看到无
33、法访问此内存地址,这是因为它已经超过了OS允许的范围。下面我们把程序进行改进:#include “stdio.h”int main()int* stack_of = malloc(sizeof(int)*100000000);int b=1;int* a;*a=b;使用gcc O3 g a.c o a进行编译,运行后会再次Core掉,使用gdb查看栈信息,请见下图:可见BUG出在第7行,也就是*a=b这句,这时我们尝试打印b的值,却发现符号表中找不到b的信息。为何?原因在于gcc使用了-O3参数,此参数可以对程序进行优化,一个负面效应是优化过程中会舍弃部分局部变量,导致调试时出现困难。在我们的
34、代码中,b声明时即赋值,随后用于为*a赋值。优化后,此变量不再需要,直接为*a赋值为1即可,如果汇编级代码上讲,此优化可以减少一条MOV语句,节省一个寄存器。此时我们的调试信息已经出现了一些扭曲,为此我们重新编译源程序,去掉-O3参数(这就解释了为何一些大型软件都会有debug版本存在,因为debug是未经优化的版本,包含了完整的符号表信息,易于调试),并重新运行,得到新的core并查看,如下图:这次就比较明显了,b中的值没有问题,有问题的是a,其指向的地址是非法区域,也就是a没有分配内存导致的Core。当然,本例中的问题其实非常明显,几乎一眼就能看出来,但不妨碍它成为一个例子,用来解释在看C
35、ore过程中,需要注意的一些问题。 网上找的用GDB调试程序GDB是一个强大的命令行调试工具。大家知道命令行的强大就是在于,其可以形成执行序列,形成脚本。UNIX下的软件全是命令行的,这给程序开发提代供了极大的便利,命令行软件的优势在于,它们可以非常容易的集成在一起,使用几个简单的已有工具的命令,就可以做出一个非常强大的功能。于是UNIX下的软件比Windows下的软件更能有机地结合,各自发挥各自的长处,组合成更为强劲的功能。而Windows下的图形软件基本上是各自为营,互相不能调用,很不利于各种软件的相互集成。在这里并不是要和Windows做个什么比较,所谓“寸有所长,尺有所短”,图形化工具
36、还是有不如命令行的地方。用GDB调试程序GDB概述GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具。或许,各位比较喜欢那种图形界面方式的,像VC、BCB等IDE的调试,但如果你是在UNIX平台下做软件,你会发现GDB这个调试工具有比VC、BCB的图形化调试器更强大的功能。所谓“寸有所长,尺有所短”就是这个道理。一般来说,GDB主要帮忙你完成下面四个方面的功能:1、启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。2、可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式)3、当程序被停住时,可以检查此时你的程序中所发生的事。4、动态的改变你程序的执行环境。从
37、上面看来,GDB和一般的调试工具没有什么两样,基本上也是完成这些功能,不过在细节上,你会发现GDB这个调试工具的强大,大家可能比较习惯了图形化的调试工具,但有时候,命令行的调试工具却有着图形化工具所不能完成的功能。让我们一一看来。一个调试示例源程序:tst.c1 #include23 int func(int n)4 5 int sum=0,i;6 for(i=0; i7; i+) 8 sum+=i;9 10 return sum;11 121314 main()15 16 int i;17 long result = 0;18 for(i=1; i cc -g tst.c -o tst使用G
38、DB调试:hchen/test gdb tst - 启动GDBGNU gdb 5.1.1Copyright 2002 Free Software Foundation, Inc.GDB is free software, covered by the GNU General Public License, and you arewelcome to change it and/or distribute copies of it under certain conditions.Type show copying to see the conditions.There is absolutel
39、y no warranty for GDB. Type show warranty for details.This GDB was configured as i386-suse-linux.(gdb) l - l命令相当于list,从第一行开始例出原码。1 #include23 int func(int n)4 5 int sum=0,i;6 for(i=0; i 7 8 sum+=i;9 10 return sum;(gdb) - 直接回车表示,重复上一次命令11 121314 main()15 16 int i;17 long result = 0;18 for(i=1; i=100;
40、 i+)19 20 result += i;(gdb) break 16 - 设置断点,在源程序第16行处。Breakpoint 1 at 0x8048496: file tst.c, line 16.(gdb) break func - 设置断点,在函数func()入口处。Breakpoint 2 at 0x8048456: file tst.c, line 5.(gdb) info break - 查看断点信息。Num Type Disp Enb Address What1 breakpoint keep y 0x08048496 in main at tst.c:162 breakpoi
41、nt keep y 0x08048456 in func at tst.c:5(gdb) r - 运行程序,run命令简写Starting program: /home/hchen/test/tstBreakpoint 1, main () at tst.c:17 - 在断点处停住。17 long result = 0;(gdb) n - 单条语句执行,next命令简写。18 for(i=1; i=100; i+)(gdb) n20 result += i;(gdb) n18 for(i=1; i=100; i+)(gdb) n20 result += i;(gdb) c - 继续运行程序,c
42、ontinue命令简写。Continuing.result1-100 = 5050 -程序输出。Breakpoint 2, func (n=250) at tst.c:55 int sum=0,i;(gdb) n6 for(i=1; i=n; i+)(gdb) p i - 打印变量i的值,print命令简写。$1 = 134513808(gdb) n8 sum+=i;(gdb) n6 for(i=1; i=n; i+)(gdb) p sum$2 = 1(gdb) n8 sum+=i;(gdb) p i$3 = 2(gdb) n6 for(i=1; i=n; i+)(gdb) p sum$4 =
43、 3(gdb) bt - 查看函数堆栈。#0 func (n=250) at tst.c:5#1 0x080484e4 in main () at tst.c:24#2 0x400409ed in _libc_start_main () from /lib/libc.so.6(gdb) finish - 退出函数。Run till exit from #0 func (n=250) at tst.c:50x080484e4 in main () at tst.c:2424 printf(result1-250 = %d /n, func(250) );Value returned is $6
44、= 31375(gdb) c - 继续运行。Continuing.result1-250 = 31375 -程序输出。Program exited with code 027. -程序退出,调试结束。(gdb) q 好了,有了以上的感性认识,还是让我们来系统地认识一下gdb吧。使用GDB一般来说GDB主要调试的是C/C+的程序。要调试C/C+的程序,首先在编译时,我们必须要把调试信息加到可执行文件中。使用编译器(cc/gcc/g+)的 -g 参数可以做到这一点。如: cc -g hello.c -o hello g+ -g hello.cpp -o hello如果没有-g,你将看不见程序的函数
45、名、变量名,所代替的全是运行时的内存地址。当你用-g把调试信息加入之后,并成功编译目标代码以后,让我们来看看如何用gdb来调试他。启动GDB的方法有以下几种:1、gdbprogram也就是你的执行文件,一般在当然目录下。2、gdb core用gdb同时调试一个运行程序和core文件,core是程序非法执行后core dump后产生的文件。3、gdb如果你的程序是一个服务程序,那么你可以指定这个服务程序运行时的进程ID。gdb会自动attach上去,并调试他。program应该在PATH环境变量中搜索得到。GDB启动时,可以加上一些GDB的启动开关,详细的开关可以用gdb -help查看。我在下
46、面只例举一些比较常用的参数:-symbols-s从指定文件中读取符号表。-se file从指定文件中读取符号表信息,并把他用在可执行文件中。-core-c调试时core dump的core文件。-directory-d加入一个源文件的搜索路径。默认搜索路径是环境变量中PATH所定义的路径。GDB的命令概貌启动gdb后,就你被带入gdb的调试环境中,就可以使用gdb的命令开始调试程序了,gdb的命令可以使用help命令来查看,如下所示:/home/hchen gdbGNU gdb 5.1.1Copyright 2002 Free Software Foundation, Inc.GDB is f
47、ree software, covered by the GNU General Public License, and you arewelcome to change it and/or 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.This GDB was configured as i386-suse-linux.
48、(gdb) helpList of classes of commands:aliases - Aliases of other commandsbreakpoints - Making program stop at certain pointsdata - Examining datafiles - Specifying and examining filesinternals - Maintenance commandsobscure - Obscure featuresrunning - Running the programstack - Examining the stacksta
49、tus - Status inquiriessupport - Support facilitiestracepoints - Tracing of program execution without stopping the programuser-defined - User-defined commandsType help followed by a class name for a list of commands in that class.Type help followed by command name for full documentation.Command name
50、abbreviations are allowed if unambiguous.(gdb)gdb的命令很多,gdb把之分成许多个种类。help命令只是例出gdb的命令种类,如果要看种类中的命令,可以使用help 命令,如:help breakpoints,查看设置断点的所有命令。也可以直接help 来查看命令的帮助。gdb中,输入命令时,可以不用打全命令,只用打命令的前几个字符就可以了,当然,命令的前几个字符应该要标志着一个唯一的命令,在Linux下,你可以敲击两次TAB键来补齐命令的全称,如果有重复的,那么gdb会把其例出来。示例一:在进入函数func时,设置一个断点。可以敲入break
51、func,或是直接就是b func(gdb) b funcBreakpoint 1 at 0x8048458: file hello.c, line 10.示例二:敲入b按两次TAB键,你会看到所有b打头的命令:(gdb) bbacktrace break bt(gdb)示例三:只记得函数的前缀,可以这样:(gdb) b make_ (再按下一次TAB键,你会看到:)make_a_section_from_file make_environmake_abs_section make_function_typemake_blockvector make_pointer_typemake_clea
52、nup make_reference_typemake_command make_symbol_completion_list(gdb) b make_GDB把所有make开头的函数全部例出来给你查看。示例四:调试C+的程序时,有可以函数名一样。如:(gdb) b bubble( M-?bubble(double,double) bubble(int,int)(gdb) b bubble(你可以查看到C+中的所有的重载函数及参数。(注:M-?和“按两次TAB键”是一个意思)要退出gdb时,只用发quit或命令简称q就行了。GDB中运行UNIX的shell程序在gdb环境中,你可以执行UNIX的shell的命令,使用gdb的shell命令来完成:shell调用UNIX的shell来执行,环境变量SHELL中定义的UNIX的shell将会被用来执行,如果SHELL没有定义,那就使用UNIX的标准s
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 广东医科大学《网络技术》2023-2024学年第二学期期末试卷
- 兰州工商学院《产品设计系统设计》2023-2024学年第二学期期末试卷
- 民办万博科技职业学院《通信原理Ⅰ》2023-2024学年第二学期期末试卷
- 淮阴师范学院《数据仓库》2023-2024学年第二学期期末试卷
- 承德护理职业学院《雕塑》2023-2024学年第二学期期末试卷
- 甘肃林业职业技术学院《机械设计课程设计A》2023-2024学年第二学期期末试卷
- 南京交通职业技术学院《高分子科学基础》2023-2024学年第二学期期末试卷
- 浙江海洋大学《传播学研究方法与应用》2023-2024学年第二学期期末试卷
- 珠海科技学院《城市公共中心设计》2023-2024学年第二学期期末试卷
- 信阳职业技术学院《公共管理理论基础》2023-2024学年第二学期期末试卷
- 2024年食品安全知识考试题库
- 2024年保密工作培训
- 短视频内容课件
- 品类创新学习通超星期末考试答案章节答案2024年
- 2024年黑龙江省龙东地区中考英语试卷(含答案与解析)
- GB/T 44577-2024商用电动洗碗机性能测试方法
- 抖音主播合同范本
- DB50∕T 995-2020 新增耕地质量评定技术规范
- 心血管内科专病数据库建设及研究
- 康复科并发症二次残疾
- 《工业机器人工作站应用实训》项目三工业机器人涂胶工作站的应用实训课件
评论
0/150
提交评论