收藏 分享(赏)

第9次课 第四章 Linux平台上的软件开发(2).ppt

上传人:Facebook 文档编号:3169145 上传时间:2018-10-05 格式:PPT 页数:74 大小:182KB
下载 相关 举报
第9次课 第四章 Linux平台上的软件开发(2).ppt_第1页
第1页 / 共74页
第9次课 第四章 Linux平台上的软件开发(2).ppt_第2页
第2页 / 共74页
第9次课 第四章 Linux平台上的软件开发(2).ppt_第3页
第3页 / 共74页
第9次课 第四章 Linux平台上的软件开发(2).ppt_第4页
第4页 / 共74页
第9次课 第四章 Linux平台上的软件开发(2).ppt_第5页
第5页 / 共74页
点击查看更多>>
资源描述

1、第四章 Linux平台上的软件开发,本章概要程序开发过程代码生成工具多模块软件的编译和链接源代码调试库的开发、调试和使用RCS和CVS的版本控制,2018年10月5日星期五,2,4.4 源代码调试,4.4.1 源代码调试,4.4.2 GNU调试器gdb,2018年10月5日星期五,3,故障程序:编译阶段没有问题的程序。当运行时产生错误,要么程序崩溃,要么产生错误的输出结果。这意味着你的程序在语法上正确,但存在逻辑错误。这样的程序称为“故障”程序。 程序的动态分析:就是运行时的程序分析。这个阶段包含调试、跟踪和软件的性能监测,以及根据产品的需要对其进行的测试。,4.4.1 源代码调试,2018年

2、10月5日星期五,4,调试器,标识出程序运行时产生问题的原因称为调试。 标识出问题代码是调试过程中最困难和最耗时的部分。需要有正确有效的方法及一个调试工具。 这种工具可以运行你的程序并允许你和它进行交互并跟踪它的执行。这样的程序就叫做调试器。,2018年10月5日星期五,5,调试与测试,在调试中,我们以不能工作的程序开始。 程序崩溃; 最简单的输入下也未产生预期结果; 在测试中,我们以正常工作的程序开始,并输入不同的数据(期望的和不期望的)运行程序,确保程序产生预期结果。,2018年10月5日星期五,6,调试软件的途径,输出变量方式。许多程序员喜欢使用printf或cout语句在程序中合适的地

3、方显示程序变量的值,这样来帮助找到bug的根源。这种技术简单易行,在调试小程序时效果很好。 使用调试工具。调试工具多基于文本界面。符号调试器包含的工具有:,2018年10月5日星期五,7,符号调试器包含的工具,运行程序 设置断点 单步调试 展示源代码 编辑源代码 访问和修改变量 跟踪程序的执行 显示程序栈上的活动记录 搜索函数、变量和目标 显示变量或表达式的值,2018年10月5日星期五,8,GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具。调试器是这样一种程序,它能让你观察另一个程序在执行时的内部活动,或程序出错时发生了什么。 GDB调试器是基于文本的调试器。我们使用gdb命令

4、调用gdb调试器。,4.4.2 GNU调试器gdb,2018年10月5日星期五,9,在命令行上键入 gdb 并按回车键就可以运行 gdb 了, 如果一切正常的话, gdb 将被启动并且你将在屏幕上看到类似的内容: GDB is free software and you are welcome to distribute copies of it under certain conditions; type “show copying“ to see the conditions. There is absolutely no warranty for GDB; type “show warr

5、anty“ for details. GDB 4.14 (i486-slakware-linux), Copyright 1995 Free Software Foundation, Inc. (gdb),2018年10月5日星期五,10,GDB主要能做四件事,以便帮助程序员找出程序中的错误。 设置程序运行的环境,运行程序。 在指定的条件下停止程序的运行。 当程序停止时,让程序员检查发生了什么。 改变程序。程序员可以试着修正某个bug引起的问题,然后继续查找另一 个bug.。,gdb 提供的功能,2018年10月5日星期五,11,GDB可调试的编程语言,C 和C+写的程序; JAVA; 部分支

6、持Modula-2和chill; 调试Pascal程序时,有一些功能不能使用; GDB还可以用来调试FORTRAN程序,尽管还不支持表达式的输入,输出变量,或类FORTRAN的词法。,2018年10月5日星期五,12,使用编译器的-g参数,一般来说GDB主要调试的是C/C+的程序。 要调试C/C+的程序,首先在编译时必须要把调试信息加到可执行文件中。 使用编译器(cc/gcc/g+)的 -g 参数可以做到这一点。如: $cc -g hello.c -o hello $g+ -g hello.cpp -o hello,2018年10月5日星期五,13,调试信息,如果没有-g,将看不见程序的函数名

7、、变量名,所代替的全是运行时的内存地址。 调试信息包含程序里的每个变量的类型和在可执行文件里的地址映射以及源代码的行号。 gdb 利用这些信息使源代码和机器码相关联。 当用-g把调试信息加入之后,并成功编译目标代码以后,再用gdb来调试。,2018年10月5日星期五,14,启动GDB的方法,最通常的命令就是使用一个参数: $gdb 可以同时为执行文件指定一个core文件: $gdb core core是程序非法执行后,core dump后产生的文件。,什么是core dump? core dump又叫核心转储, 当程序运行过程中发生异常, 程序异常退出时, 由操作系统把程序当前的内存状况存储在

8、一个core文件中, 叫core dump。,如何使用core文件? gdb -c core 文件路径 应用程序的路径 进去后输入where回车, 就可以显示程序在哪一行down掉的, 在哪个函数中。,2018年10月5日星期五,15,启动GDB的方法,也可以为要执行的文件指定一个进程号: $gdb 如:$gdb os 1234将使gdb与进程1234相联系(attach),2018年10月5日星期五,16,表 基本 gdb 命令,命 令 描 述 file 装入想要调试的可执行文件. kill 终止正在调试的程序. list 列出产生执行文件的源代码的一部分. next 执行一行源代码但不进入

9、函数内部. step 执行一行源代码而且进入函数内部. run 执行当前被调试的程序 quit 终止 gdb,2018年10月5日星期五,17,watch 使你能监视一个变量的值而不管它何时被改变. break 在代码里设置断点, 这将使程序执行到这里时被挂起. make 使你能不退出 gdb 就可以重新产生可执行文件. shell 使你能不离开 gdb 就执行 UNIX shell 命令.,2018年10月5日星期五,18,Help 的使用,在 gdb 提示符处键入help,将列出命令的分类,主要的分类有: aliases:命令别名 breakpoints:断点定义; data:数据查看;

10、files:指定并查看文件; internals:维护命令; running:程序执行; stack:调用栈查看; statu:状态查看; tracepoints:跟踪程序执行。 键入 help 后跟命令的分类名,可获得该类命令的详细清单。,2018年10月5日星期五,19,gdb中,输入命令时,可以不用打全命令,只用打命令的前几个字符就可以了,当然,命令的前几个字符应该要标志着一个唯一的命令。 在Linux下,可以敲击两次TAB键来补齐命令的全称,如果有重复的,那么gdb会把其列出来。,2018年10月5日星期五,20,示例,示例一:在进入函数func时,设置一个断点。可以敲入break f

11、unc,或是直接就是b func (gdb) b func Breakpoint 1 at 0x8048458: file hello.c, line 10. 示例二:敲入b按两次TAB键,你会看到所有b打头的命令: (gdb) b backtrace break bt (gdb),2018年10月5日星期五,21,示例三:只记得函数的前缀,可以这样:(gdb) b make_ (再按下一次TAB键,你会看到:) make_a_section_from_file make_environ make_abs_section make_function_type make_blockvector

12、make_pointer_type make_cleanup make_reference_type make_command make_symbol_completion_list (gdb) b make_ GDB把所有make开头的函数全部列出来。,2018年10月5日星期五,22,由于C+支持函数的重载。当要在某个有重载函数上设断点时,就要给出函数参数以区分不同的重载函数。 可以把整个函数用“ ”括起来。比如,要在一个叫name的函数上设断点,而这个函数被重载了(name(int)和name(float)。给出参变量以区分不同的函数: name(int) name(float) 。 技

13、巧:可以在函数名前加一个“ ”符号。然后打M-?. 得到帮助 。,2018年10月5日星期五,23,示例四:调试C+的程序时,还可以使用该方法查看函数原型。如: (gdb) b bubble( M-? bubble(double,double) bubble(int,int) (gdb) b bubble( 可以查看到C+中的所有的重载函数及参数。 (注:M-?和“按两次TAB键”是一个意思),2018年10月5日星期五,24,GDB中运行UNIX的shell程序,在gdb环境中,可以执行UNIX的shell的命令,使用gdb的shell命令来完成:shell 调用UNIX的shell来执行,

14、环境变量SHELL中定义的UNIX的shell将会被用来执行,如果SHELL没有定义,那就使用UNIX的标准shell:/bin/sh。 还有一个gdb命令是make: make 可以在gdb中执行make命令来重新build自己的程序。这个命令等价于“shell make ”。,2018年10月5日星期五,25,在GDB中运行程序,当以gdb 方式启动gdb后,gdb会在PATH路径和当前目录中搜索源文件。 如要确认gdb是否读到源文件,可使用l或list命令,看看gdb是否能列出源代码。 在gdb中,运行程序使用r或是run命令。程序的运行,需要设置下面四方面的事。,2018年10月5日星

15、期五,26,在GDB中运行程序,1、程序运行参数。 set args 可指定运行时参数。如:set args 10 20 30 40 50 show args 命令可以查看设置好的运行参数。 2、运行环境。 path 3、工作目录。在gdb中改变工作目录。 cd ,2018年10月5日星期五,27,在GDB中运行程序,4、程序的输入输出。 info terminal 显示你程序用到的终端的模式。 使用重定向控制程序输出。如:run outfile tty命令可以指定输入输出的终端设备。如:tty /dev/ttyb,2018年10月5日星期五,28,调试已运行的程序,两种方法: 1、在UNIX

16、下用ps查看正在运行的程序的PID(进程ID),然后用gdb PID格式挂接正在运行的程序。 2、先用gdb 关联上源代码,并进行gdb,在gdb中用attach命令来挂接进程的PID。并用detach来取消挂接的进程。,2018年10月5日星期五,29,attach PROCESS-ID 这个命令把一个已经运行的进程(在gdb外启动)连接入gdb,以便调试。 PROCESS-ID是进程号。(UNIX中使用ps或jobs -l来查看进程) 要使用attach命令的话,操作系统环境必须支持进程。 另外还要有向此进程发信号的权力。,2018年10月5日星期五,30,当使用attach命令时,应该先

17、使用file命令来指定进程所联系的程序源代码和符号表。 当gdb接到attach命令后第一件事就是停止进程的运行,可以使用所有gdb的命令来调试一个“连接”的进程,就象用run命令在gdb中启动它一样。 如果要进程继续运行,使用continue或c命令就行。 detach 当结束调试后可以使用此命令来断开进程和gdb的连接。,2018年10月5日星期五,31,暂停 / 恢复程序运行,调试程序中,暂停程序运行是必须的,GDB可以方便地暂停程序的运行。 可以设置程序在哪行停住,在什么条件下停住,在收到什么信号时停往等等。以便于查看运行时的变量,以及运行时的流程。 当进程被gdb停住时,可以使用in

18、fo program 来查看程序的是否在运行,进程号,被暂停的原因。,2018年10月5日星期五,32,暂停 / 恢复程序运行,在gdb中,有以下几种暂停方式: 断点(BreakPoint) 观察点(WatchPoint) 捕捉点(CatchPoint) 信号(Signals) 线程停止(Thread Stops) 如果要恢复程序运行,可以使用continue或c命令。,2018年10月5日星期五,33,设置断点(BreakPoint),用break命令来设置断点。正面有几点设置断点的方法: break 函数名 在进入指定函数时停住。C+中可以使用class:function或function

19、(type,type)格式来指定函数名。 break 行号 在指定行号停住。,2018年10月5日星期五,34,设置断点(BreakPoint),break +offset break offset 在当前行号的前面或后面的offset行停住。offiset为自然数。 break filename:linenum 在源文件filename的linenum行处停住。 break filename:function 在源文件filename的function函数的入口处停住。 break *address 在程序运行的内存地址处停住。,2018年10月5日星期五,35,break break命令没

20、有参数时,表示在下一条指令处停住。 break . if condition .可以是上述的参数,condition表示条件,在条件成立时停住。 比如在循环体中,可以设置break if i=100,表示当i为100时停住程序。 查看断点时,可使用info命令,如下所示:(注:n表示断点号) info breakpoints n info break n,2018年10月5日星期五,36,设置观察点(WatchPoint),观察点一般来观察某个表达式(变量也是一种表达式)的值是否有变化了,如果有变化,马上停住程序。 有下面的几种方法来设置观察点:,2018年10月5日星期五,37,watch

21、为表达式(变量)expr设置一个观察点。一量表达式值有变化时,马上停住程序。 rwatch 当表达式(变量)expr被读时,停住程序。 awatch 当表达式(变量)的值被读或被写时,停住程序。 info watchpoints 列出当前所设置了的所有观察点。,2018年10月5日星期五,38,设置捕捉点(CatchPoint),可设置捕捉点来补捉程序运行时的一些事件。 如:载入共享库(动态链接库)或是C+的异常。 设置捕捉点的格式为:,2018年10月5日星期五,39,catch ,当event发生时,停住程序。event可以是下面的内容: 1、throw 一个C+抛出的异常。(throw为

22、关键字) 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下有用),2018年10

23、月5日星期五,40,维护停止点,上面说了如何设置程序的停止点,GDB中的停止点也就是上述的三类。 在GDB中,如果已定义好的停止点没有用了,可以使用delete、clear、disable、enable这几个命令来进行维护。,2018年10月5日星期五,41,clear 清除所有的已定义的停止点。 clear function(type,type) clear function_name 清除所有设置在函数上的停止点。 clear 行号清除所有设置在指定行上的停止点。,2018年10月5日星期五,42,delete breakpoints range. 删除指定的断点,breakpoints为

24、断点号。如果不指定断点号,则表示删除所有的断点。range 表示断点号的范围(如:3-7)。其简写命令为d。,2018年10月5日星期五,43,比删除更好的一种方法是disable停止点。 disable了的停止点,GDB不会删除,需要时,enable即可,就好像回收站一样。 disable breakpoints range.disable所指定的停止点,breakpoints为停止点号。如果什么都不指定,表示disable所有的停止点。简写命令是dis. enable breakpoints range.enable所指定的停止点,breakpoints为停止点号。,2018年10月5日星

25、期五,44,enable breakpoints once range. enable所指定的停止点一次,当程序停止后,该停止点马上被GDB自动disable。enable breakpoints delete range. enable所指定的停止点一次,当程序停止后,该停止点马上被GDB自动删除。,2018年10月5日星期五,45,停止条件维护,设置断点时,可以设置一个条件,当条件成立时,程序自动停止,这是一个非常强大的功能。 一般来说,为断点设置一个条件,使用if关键词,后面跟其断点条件。 条件设置好后,可以用condition命令来修改断点的条件。(只有break和watch命令支持i

26、f,catch目前暂不支持if),2018年10月5日星期五,46,条件断点维护命令,condition expression bnum 修改断点号为bnum的停止条件为expression condition bnum 清除断点号为bnum的停止条件。 还有一个比较特殊的维护命令ignore,可以指定程序运行时,忽略停止条件几次。 ignore count bnum 表示忽略断点号为bnum的停止条件count次。,2018年10月5日星期五,47,为停止点设定运行命令,可以使用GDB提供的command命令来设置停止点的运行命令。 也就是说,当运行的程序在被停止住时,可以让其自动运行一些别

27、的命令,这很有利行自动化调试。 对基于GDB的自动化调试是一个强大的支持。,2018年10月5日星期五,48,command命令,commands bnum . command-list . end 为断点号bnum指写一个命令列表。当程序被该断点停住时,gdb会依次运行命令列表中的命令。,2018年10月5日星期五,49,例如:break foo if x0 commands printf “x is %dn“,x continue end 断点设置在函数foo中,断点条件是x0,如果程序被停住后,也就是,一旦x的值在foo函数中大于0,GDB会自动打印出x的值,并继续运行程序。 如果你要清

28、除断点上的命令序列,那么只要简单的执行一下commands命令,并直接在打个end就行了。,2018年10月5日星期五,50,恢复程序运行和单步调试,当程序被停住了,可以用continue命令恢复程序的运行直到程序结束,或下一个断点到来。也可以使用step或next命令单步跟踪程序。continue ignore-count c ignore-count fg ignore-count 恢复程序运行,直到程序结束,或是下一个断点到来。ignore-count表示忽略其后的断点次数。 continue,c,fg三个命令都是一样的意思。,2018年10月5日星期五,51,step,单步跟踪,如果有

29、函数调用,它会进入该函数。 进入函数的前提是,此函数被编译有debug信息。很像VC等工具中的step in。 后面可以加count也可以不加,不加表示一条条地执行,加表示执行后面的count条指令,然后再停住。,2018年10月5日星期五,52,next,同样单步跟踪,如果有函数调用,它不会进入该函数。很像VC等工具中的step over。 后面可以加count也可以不加,不加表示一条条地执行,加表示执行后面的count条指令,然后再停住。,2018年10月5日星期五,53,set step-modeset step-mode on 打开step-mode模式,于是,在进行单步跟踪时,程序不

30、会因为没有debug信息而不停住。这个参数有很利于查看机器码。 set step-mod off 关闭step-mode模式。 finish 运行程序,直到当前函数完成返回。并打印函数返回时的堆栈地址和返回值及参数值等信息。,2018年10月5日星期五,54,信号(Signals),GDB有能力在调试程序的时候处理任何一种信号,告诉GDB需要处理哪一种信号。 可以要求GDB收到你所指定的信号时,马上停住正在运行的程序,以供进行调试。 可以用GDB的handle命令来完成这一功能。,2018年10月5日星期五,55,handle,在GDB中定义一个信号处理。信号可以以SIG开头或不以SIG开头,

31、可以用定义一个要处理信号的范围(如:SIGIO- SIGKILL,表示处理从SIGIO信号到SIGKILL的信号,其中包括SIGIO,SIGIOT,SIGKILL三个信号), 也可以使用关键字 all来标明要处理所有的信号。一旦被调试的程序接收到信号,运行程序马上会被GDB停住,以供调试。 其可以是以下几种关键字的一个或多个。,2018年10月5日星期五,56,nostop 当被调试的程序收到信号时,GDB不会停住程序的运行,但会打出消息告诉你收到这种信号。 stop 当被调试的程序收到信号时,GDB会停住你的程序。 print 当被调试的程序收到信号时,GDB会显示出一条信息 noprint

32、 当被调试的程序收到信号时,GDB不会告诉你收到信号的信息。 pass noignore 当被调试的程序收到信号时,GDB不处理信号。这表示,GDB会把这个信号交给被调试程序处理。 nopass ignore当被调试的程序收到信号时,GDB不会让被调试程序来处理这个信号。,2018年10月5日星期五,57,查看栈信息,当程序被停住了,你需要做的第一件事就是查看程序是在哪里停住的。 当程序调用了一个函数,函数的地址,函数参数,函数内的局部变量都会被压入“栈”(Stack)中。 可以用GDB命令来查看当前的栈中的信息。,2018年10月5日星期五,58,查看函数调用栈信息的GDB命令,backtr

33、ace bt 打印当前的函数调用栈的所有信息。如: (gdb) bt #0 func (n=250) at tst.c:6 #1 0x08048524 in main (argc=1, argv=0xbffff674) at tst.c:30 #2 0x400409ed in_libc_start_main () from /lib/libc.so.6 从上可以看出函数的调用栈信息:_libc_start_main main() func(),2018年10月5日星期五,59,backtrace bt n是一个正整数,表示只打印栈顶上n层的栈信息。 backtrace bt -n表一个负整数,

34、表示只打印栈底下n层的栈信息。 如果要查看某一层的信息,需要在切换当前的栈, 一般来说,程序停止时,最顶层的栈就是当前栈,如果你要查看栈下面层的详细信息,首先要做的是切换当前栈。,2018年10月5日星期五,60,frame f n是一个从0开始的整数,是栈中的层编号。比如:frame 0,表示栈顶,frame 1,表示栈的第二层。 up 表示向栈的上面移动n层,可以不打n,表示向上移动一层。 down 表示向栈的下面移动n层,可以不打n,表示向下移动一层。,2018年10月5日星期五,61,查看当前栈层的信息,你可以用以下GDB命令: frame 或 f 会打印出这些信息:栈的层编号,当前的

35、函数名,函数参数值,函数所在文件及行号,函数执行到的语句。 info frame info f 这个命令会打印出更为详细的当前栈层的信息,只不过,大多数都是运行时的内存地址。 比如:函数地址,调用函数的地址,被调用函数的地址,目前的函数是由什么样的程序语言写成的、函数参数地址及值、局部变量的地址等等。,2018年10月5日星期五,62,如:(gdb) info fStack level 0, frame at 0xbffff5d4:eip = 0x804845d in func (tst.c:6); saved eip 0x8048524 called by frame at 0xbffff6

36、0csource language c.Arglist at 0xbffff5d4, args: n=250Locals at 0xbffff5d4, Previous frames sp is 0x0Saved registers:ebp at 0xbffff5d4, eip at 0xbffff5d8,2018年10月5日星期五,63,info args 打印出当前函数的参数名及其值。 info locals 打印出当前函数中所有局部变量及其值。 info catch 打印出当前的函数中的异常处理信息。,2018年10月5日星期五,64,查看源程序,GDB 可以打印出所调试程序的源代码,当

37、然,在程序编译时一定要加上-g的参数,把源程序信息编译到执行文件中。 当程序停下来以后, GDB会报告程序停在了那个文件的第几行上。可以用list命令来打印程序的源代码。 下面看看查看源代码的GDB命令。,2018年10月5日星期五,65,显示源代码,list linenum 显示程序第linenum行的周围的源程序。 list function 显示函数名为function的函数的源程序。 list 显示当前行后面的源程序。 list 显示当前行前面的源程序。,2018年10月5日星期五,66,显示源代码,一般是打印当前行的上5行和下5行,如果显示函数是是上2行下8行,默认是10行,当然,也

38、可以定制显示的范围,使用下面命令可以设置一次显示源程序的行数。 set listsize 设置一次显示源代码的行数。,2018年10月5日星期五,67,搜索源代码,GDB还提供了源代码搜索的命令: forward-search 向前面搜索。 reverse-search 全部搜索。 其中,可以使用正则表达式,即一个字符串的匹配模式。,2018年10月5日星期五,68,源代码的内存,你可以使用info line命令来查看源代码在内存中的地址。 info line后面可以跟“行号”,“函数名”,“文件名:行号”,“文件名:函数名”,这个命令会打印出所指定的源码在运行时的内存地址, 如: (gdb)

39、 info line tst.c:func Line 5 of “tst.c“ starts at address 0x8048456 and ends at 0x804845d .,2018年10月5日星期五,69,查看汇编代码,还有一个命令(disassemble)你可以查看源程序的当前执行时的机器码,这个命令会把目前内存中的指令dump出来。 如下面的示例表示查看函数func的汇编代码。,2018年10月5日星期五,70,(gdb) disassemble func Dump of assembler code for function func: 0x8048450 : push %e

40、bp 0x8048451 : mov %esp,%ebp 0x8048453 : sub $0x18,%esp 0x8048456 : movl $0x0,0xfffffffc(%ebp) 0x804845d : movl $0x1,0xfffffff8(%ebp) 0x8048464 : mov 0xfffffff8(%ebp),%eax 0x8048467 : cmp 0x8(%ebp),%eax 0x804846a : jle 0x8048470 0x804846c : jmp 0x8048480 0x804846e : mov %esi,%esi 0x8048470 : mov 0xf

41、ffffff8(%ebp),%eax 0x8048473 : add %eax,0xfffffffc(%ebp) 0x8048476 : incl 0xfffffff8(%ebp) 0x8048479 : jmp 0x8048464 0x804847b : nop 0x804847c : lea 0x0(%esi,1),%esi 0x8048480 : mov 0xfffffffc(%ebp),%edx 0x8048483 : mov %edx,%eax 0x8048485 : jmp 0x8048487 0x8048487 : mov %ebp,%esp 0x8048489 : pop %e

42、bp 0x804848a : ret End of assembler dump.,2018年10月5日星期五,71,gdb 使用范例,清单 一个有错误的 C 源程序 bugging.c #include #include static char buff 256; static char* string; int main () printf (“Please input a string: “);gets (string);printf (“nYour string is: %sn“, string); ,2018年10月5日星期五,72,上面这个程序非常简单,其目的是接受用户的输入,然后

43、将用户的输入打印出来。该程序使用了一个未经过初始化的字符串地址 string,因此,编译并运行之后,将出现 Segment Fault 错误: $ gcc -o test -g test.c $ ./test Please input a string: asfd Segmentation fault (core dumped) 为了查找该程序中出现的问题,我们利用 gdb,并按如下的步骤进行:,2018年10月5日星期五,73,1运行 gdb bugging 命令,装入 bugging 可执行文件; 2执行装入的 bugging 命令; 3使用 where 命令查看程序出错的地方; 4利用 list 命令查看调用 gets 函数附近的代码; 5唯一能够导致 gets 函数出错的因素就是变量 string。用 print 命令查看 string 的值;,2018年10月5日星期五,74,6在 gdb 中,我们可以直接修改变量的值,只要将 string 取一个合法的指针值就可以了,为此,我们在第 11 行处设置断点; 7程序重新运行到第 11 行处停止,这时,我们可以用 set variable 命令修改 string 的取值; 8然后继续运行,将看到正确的程序运行结果。,

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

当前位置:首页 > 中等教育 > 小学课件

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


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

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

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