ImageVerifierCode 换一换
格式:DOC , 页数:28 ,大小:293KB ,
资源ID:4764114      下载积分:5 金币
验证码下载
登录下载
邮箱/手机:
图形码:
验证码: 获取验证码
温馨提示:
支付成功后,系统会自动生成账号(用户名为邮箱或者手机号,密码是验证码),方便下次登录下载和查询订单;
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

开通VIP
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.zixin.com.cn/docdown/4764114.html】到电脑端继续下载(重复下载【60天内】不扣币)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

开通VIP折扣优惠下载文档

            查看会员权益                  [ 下载后找不到文档?]

填表反馈(24小时):  下载求助     关注领币    退款申请

开具发票请登录PC端进行申请。


权利声明

1、咨信平台为文档C2C交易模式,即用户上传的文档直接被用户下载,收益归上传人(含作者)所有;本站仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。所展示的作品文档包括内容和图片全部来源于网络用户和作者上传投稿,我们不确定上传用户享有完全著作权,根据《信息网络传播权保护条例》,如果侵犯了您的版权、权益或隐私,请联系我们,核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
2、文档的总页数、文档格式和文档大小以系统显示为准(内容中显示的页数不一定正确),网站客服只以系统显示的页数、文件格式、文档大小作为仲裁依据,个别因单元格分列造成显示页码不一将协商解决,平台无法对文档的真实性、完整性、权威性、准确性、专业性及其观点立场做任何保证或承诺,下载前须认真查看,确认无误后再购买,务必慎重购买;若有违法违纪将进行移交司法处理,若涉侵权平台将进行基本处罚并下架。
3、本站所有内容均由用户上传,付费前请自行鉴别,如您付费,意味着您已接受本站规则且自行承担风险,本站不进行额外附加服务,虚拟产品一经售出概不退款(未进行购买下载可退充值款),文档一经付费(服务费)、不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
4、如你看到网页展示的文档有www.zixin.com.cn水印,是因预览和防盗链等技术需要对页面进行转换压缩成图而已,我们并不对上传的文档进行任何编辑或修改,文档下载后都不会有水印标识(原文档上传前个别存留的除外),下载后原文更清晰;试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓;PPT和DOC文档可被视为“模板”,允许上传人保留章节、目录结构的情况下删减部份的内容;PDF文档不管是原文档转换或图片扫描而得,本站不作要求视为允许,下载前可先查看【教您几个在下载文档中可以更好的避免被坑】。
5、本文档所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用;网站提供的党政主题相关内容(国旗、国徽、党徽--等)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
6、文档遇到问题,请及时联系平台进行协调解决,联系【微信客服】、【QQ客服】,若有其他问题请点击或扫码反馈【服务填表】;文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“【版权申诉】”,意见反馈和侵权处理邮箱:1219186828@qq.com;也可以拔打客服电话:4009-655-100;投诉/维权电话:18658249818。

注意事项

本文(142045_应用-Valgrind-发现-Linux-程序的内存问题.doc)为本站上传会员【二***】主动上传,咨信网仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知咨信网(发送邮件至1219186828@qq.com、拔打电话4009-655-100或【 微信客服】、【 QQ客服】),核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载【60天内】不扣币。 服务填表

142045_应用-Valgrind-发现-Linux-程序的内存问题.doc

1、简介 调试程序有很多方法,例如向屏幕上打印消息,使用调试器,或者只需仔细考虑程序如何运行,并对问题进行有根有据的猜测。 在修复 bug 之前,首先要确定在源程序中的位置。例如,当一个程序产生崩溃或生成核心转储(core dump)时,您就需要了解是哪行代码发生了崩溃。在找到有问题的代码行之后,就可以确定这个函数中变量的值,函数是如何调用的,更具体点说,为什么会发 生这种错误。使用调试器查找这些信息非常简单。 本文将简要介绍几种用于修复一些很难通过可视化地检查代码而发现的 bug 的技术,并阐述了如何使用在 Linux on Power 架构上可用的工具。 回页首 调试内存问题的工

2、具和技术 动态内存分配看起来似乎非常简单:您可以根据需要分配内存 —— 使用 malloc() 或其变种 —— 并在不需要时释放这些内存。实际上,内存管理的问题是软件中最为常见的 bug,因为通常在程序启动时这些问题并不明显。例如,程序中的内存泄漏可能开始并不为人注意,直到经过多天甚至几个月的运行才会被发现。接下来的几节将 简要介绍如何使用流行的调试器 Valgrind 来发现并调试这些最常见的内存 bug。 在开始使用任何调试工具之前,请考虑这个工具是否对重新编译应用程序有益,是否可以支持具有调试信息的库(-g 选项)。如果没有启用调试信息,调试工具可以做的最好的事情也不过是猜测一段特定

3、的代码是属于哪个函数的。这使得错误消息和概要分析输出几乎没有什么用处。使用 -g 选项,您就有可能获得一些信息来直接指出相关的代码行。 Valgrind Valgrind 已经在 Linux 应用程序开发社区中广泛用来调试应用程序。它尤其擅长发现内存管理的问题。它可以检查程序运行时的内存泄漏问题。这个工具目前正由 Julian Seward 进行开发,并由 Paul Mackerras 移植到了 Power 架构上。 要安装 Valgrind,请从 Valgrind 的 Web 站点上下载源代码(参阅 参考资料)。切换到 Valgrind 目录,并执行下面的命令: # make #

4、make check # make install Valgrind 的错误报告 Valgrind 的输出格式如下: 清单 1. Valgrind 的输出消息 # valgrind du –x –s . . ==29404== Address 0x1189AD84 is 0 bytes after a block of size 12 alloc'd ==29404== at 0xFFB9964: malloc (vg_replace_malloc.c:130) ==29404== by 0xFEE1AD0: str

5、dup (in /lib/tls/libc.so.6) ==29404== by 0xFE94D30: setlocale (in /lib/tls/libc.so.6) ==29404== by 0x10001414: main (in /usr/bin/du) ==29404== 是进程的 ID。消息 Address 0x1189AD84 is 0 bytes after a block of size 12 alloc'd 说明在这个 12 字节的数组后面没有存储空间了。第二行以及后续几行说明内存是在 130 行(vg_replace_malloc.c)的 strd

6、up() 程序中进行分配的。strdup() 是在 libc.so.6 库的 setlocale() 中调用的;main() 调用了 setlocale()。 未初始化的内存 最为常见的一个 bug 是程序使用了未初始化的内存。未初始化的数据可能来源于: · 未经初始化的变量 · malloc 函数所分配的数据,在写入值之前使用了 下面这个例子使用了一个未初始化的数组: 清单 2. 使用未初始化的内存 2 { 3 int i[5]; 4 5 if (i

7、[0] == 0) 6 i[1]=1; 7 return 0; 8 } 在这个例子中,整数数组 i[5] 没有进行初始化;因此,i[0] 包含的是一个随机数。因此使用 i[0] 的值来判断一个条件分支就会导致不可预期的问题。Valgrind 可以很容易捕获这种错误条件。当您使用 Valgrind 运行这个程序时,就会接收到下面的消息: 清单 3. Valgrind 的输出消息 # gcc –g –o test1 test1.c # valgrind ./

8、test1 . . ==31363== ==31363== Conditional jump or move depends on uninitialised value(s) ==31363== at 0x1000041C: main (test1.c:5) ==31363== ==31363== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 7 from 1) ==31363== malloc/free: in use at exit: 0 bytes in 0 blocks. ==31363== ma

9、lloc/free: 0 allocs, 0 frees, 0 bytes allocated. ==31363== For counts of detected errors, rerun with: -v ==31363== No malloc'd blocks -- no leaks are possible. Valgrind 的输出说明,有一个条件分支依赖于文件 test1.c 中第 5 行中的一个未初始化的变量。 内存泄漏 内存泄漏是另外一个常见的问题,也是很多程序中最难判断的问题。内存泄漏的主要表现为:当程序连续运行时,与程序相关的内 存(或堆)变得越来越大。结果是

10、当这个程序所消耗的内存达到系统的上限时,就会自己崩溃;或者会出现更严重的情况:挂起或导致系统崩溃。下面是一个有内 存泄漏 bug 的示例程序: 清单 4. 内存泄漏示例 1 int main(void) 2 { 3 char *p1; 4 char *p2; 5 6 p1 = (char *) malloc(512); 7 p2 = (char *) malloc(512);

11、 8 9 p1=p2; 10 11 free(p1); 12 free(p2); 13 } 上面的代码分别给字符指针 p1 和 p2 分配了两个 512 字节的内存块,然后将指向第一个内存块的指针设置为指向第二个内存块。结果是,第二个内存块的地址丢失了,并导致内存泄漏。在使用 Valgrind 运行这个程序时,会返回如下的消息: 清单 5. Valgrind 的输出消息 # gcc –g –o test2 test2.c # va

12、lgrind ./test2 . . ==31468== Invalid free() / delete / delete[] ==31468== at 0xFFB9FF0: free (vg_replace_malloc.c:152) ==31468== by 0x100004B0: main (test2.c:12) ==31468== Address 0x11899258 is 0 bytes inside a block of size 512 free'd ==31468== at 0xFFB9FF0: free (vg_replace_malloc.

13、c:152) ==31468== by 0x100004A4: main (test2.c:11) ==31468== ==31468== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 7 from 1) ==31468== malloc/free: in use at exit: 512 bytes in 1 blocks. ==31468== malloc/free: 2 allocs, 2 frees, 1024 bytes allocated. ==31468== For counts of detecte

14、d errors, rerun with: -v ==31468== searching for pointers to 1 not-freed blocks. ==31468== checked 167936 bytes. ==31468== ==31468== LEAK SUMMARY: ==31468== definitely lost: 512 bytes in 1 blocks. ==31468== possibly lost: 0 bytes in 0 blocks. ==31468== still reachable: 0 bytes in

15、0 blocks. ==31468== suppressed: 0 bytes in 0 blocks. ==31468== Use --leak-check=full to see details of leaked memory. 正如您可以看到的一样,Valgrind 报告说这个程序中有 512 字节的内存丢失了。 非法写/读 这种情况发生在程序试图对一个不属于程序本身的内存地址进行读写时。在有些系统上,在发生这种错误时,程序会异常结束,并产生一个段错误。下面这个例子就是一个常见的 bug,它试图读写一个超出数组边界的元素。 清单 6. 非法读写

16、 1 int main() { 2 int i, *iw, *ir; 3 4 iw = (int *)malloc(10*sizeof(int)); 5 ir = (int *)malloc(10*sizeof(int)); 6 7 8 for (i=0; i<11; i++) 9 iw[i] = i; 10 11

17、 for (i=0; i<11; i++) 12 ir[i] = iw[i]; 13 14 free(iw); 15 free(ir); 16 } 从这个程序中我们可以看出,对于 iw[10] 和 ir[10] 的访问都是非法的,因为 iw 和 ir 都只有 10 个元素,分别是从 0 到 9。请注意 int iw[10 ] 和 iw = (int *)malloc(10*sizeof(int)) 是等效的 —— 它们都是用来给一个整数数组 iw

18、 分配 10 个元素。 当您使用 Valgrind 运行这个程序时,会返回如下的消息: 清单 7. Valgrind 的输出消息 # gcc –g –o test3 test3.c # valgrind ./test3 . . ==31522== Invalid write of size 4 ==31522== at 0x100004C0: main (test3.c:9) ==31522== Address 0x11899050 is 0 bytes after a block of size 40 alloc'd ==3

19、1522== at 0xFFB9964: malloc (vg_replace_malloc.c:130) ==31522== by 0x10000474: main (test10.c:4) ==31522== ==31522== Invalid read of size 4 ==31522== at 0x1000050C: main (test3.c:12) ==31522== Address 0x11899050 is 0 bytes after a block of size 40 alloc'd ==31522== at 0xFFB9964:

20、malloc (vg_replace_malloc.c:130) ==31522== by 0x10000474: main (test10.c:4) ==31522== ==31522== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 7 from 1) ==31522== malloc/free: in use at exit: 0 bytes in 0 blocks. ==31522== malloc/free: 2 allocs, 2 frees, 84 bytes allocated. ==31522==

21、 For counts of detected errors, rerun with: -v ==31522== No malloc'd blocks -- no leaks are possible. 在 test3.c 的第 9 行发现一个非法的 4 字节写操作,在第 12 行发现一个非法的 4 字节读操作。 Valgrind 也可以帮助判断内存误用的问题,例如: · 读/写已经释放的内存 · C++ 环境中错误地使用 malloc/new 与 free/delete 的配对 下面这个列表介绍了 POWER 架构上 Valgrind 的状态: · memcheck 和

22、 addrcheck 工具都可以很好地工作。然而,其他工具还没有进行大量的测试。另外,Helgrind (一个数据竞争的检测程序)在 POWER 上尚不能使用。 · 所有的 32 位 PowerPC? 用户模式的指令都可以支持,除了两条非常少用的指令:lswx 和 stswx。具体来说,所有的浮点和 Altivec(VMX)指令都可以支持。 · Valgrind 可以在 32 位或 64 位 PowerPC/Linux 内核上工作,但是只能用于 32 位的可执行程序。 有关 Valgrind 内存调试的更多信息,请访问 Valgrind HOW TO 站点。还可以参阅 Steve Bes

23、t 的“Debugging Memory Problems”(Linux Magazine,2003 年 5 月)。参考资料 中有它们的链接 除了 Valgrind 之外,还可以使用其他几个内存调试工具;例如,Memwatch 和 Electric Fence。 回页首 调试其他程序问题的工具和技术 除了内存 bug 之外,开发人员通常还会碰到程序虽然能够成功编译,但是在运行时却会产生内核转储或段错误的问题。有时在程序完成之后,程序的输出可能与所期望或设计的不 同。在这两种情况中,可能代码中存在您认为正确而实际上错误的情况。接下来的几节中介绍的调试器将帮助您找到这些情况的原因。

24、GNU 项目调试器 GDB(GNU 项目调试器)可以让您了解程序在执行时“内部” 究竟在干些什么,以及在程序发生崩溃的瞬间正在做什么。 GDB 做以下 4 件主要的事情来帮助您捕获程序中的 bug: · 在程序启动之前指定一些可以影响程序行为的变量或条件 · 在某个指定的地方或条件下暂停程序 · 在程序停止时检查已经发生了什么 · 在程序执行过程中修改程序中的变量或条件,这样就可以体验修复一个 bug 的成果,并继续了解其他 bug 要调试的程序可以是使用 C、C++、Pascal、Objective-C 以及其他很多语言编写的。GDB 的二进制文件名是 gdb。 gdb 中

25、有很多命令。使用 help 命令可以列出所有的命令,以及关于如何使用这些命令的介绍。下表给出了最常用的 GDB 命令。 表 1. gdb 中最常用的命令 命令 说明 例子 help 显示命令类别 help - 显示命令类别 help breakpoints - 显示属于 breakpoints 类别的命令 help break - 显示 break 命令的解释 run 启动所调试的程序 ? kill 终止正在调试的程序的执行 通常这会在要执行的代码行已经超过了您想要调试的代码时使用。执行 kill 会重置断点,并从头再次运行这个程序 co

26、nt 所调试的程序运行到一个断点、异常或单步之后,继续执行 ? info break 显示当前的断点或观察点 ? break 在指定的行或函数处设置断点 break 93 if i=8 - 当变量 i 等于 8 时,在第 93 行停止程序执行 Step 单步执行程序,直到它到达一个不同的源代码行。您可以使用 s 来代表 step 命令 ? Next 与 step 命令类似,只是它不会“单步跟踪到”子例程中 ? print 打印一个变量或表达式的值 print pointer - 打印变量指针的内容 print *pointer - 打印指

27、针所指向的数据结构的内容 delete 删除某些断点或自动显示表达式 delete 1 - 删除断点 1。断点可以通过 info break 来显示 watch 为一个表达式设置一个观察点。当表达式的值发生变化时,这个观察点就会暂停程序的执行 ? where 打印所有堆栈帧的栈信息 where - 不使用参数,输出当前线程的堆栈信息 where all - 输出当前线程组中所有线程的堆栈信息 where threadindex - 输出指定线程的堆栈信息 attach 开始查看一个已经运行的进程 attach - 附加到进程 p

28、rocess_id 上。process_id 可以使用 ps 命令找到 info thread 显示当前正在运行的线程 ? thread apply threadno command 对一个线程运行 gdb 命令 thread apply 3 where - 对线程 3 运行 where 命令 Thread threadno 选择一个线程作为当前线程 ? 如果一个程序崩溃了,并生成了一个 core 文件,您可以查看 core 文件来判断进程结束时的状态。使用下面的命令启动 gdb: # gdb programname corefilename 要调试一个

29、 core 文件,您需要可执行程序、源代码文件以及 core 文件。要对一个 core 文件启动 gdb,请使用 -c 选项: # gdb -c core programname gdb 会显示是哪行代码导致这个程序产生了核心转储。 默认情况下,核心转储在 Novell 的 SUSE LINUX Enterprise Server 9(SLES 9)和 Red Hat? Enterprise Linux Advanced Server(RHEL AS 4)上都是禁用的。要启用核心转储,请以 root 用户的身份在命令行中执行 ulimit –c unlimited。 清单 8 中

30、的例子阐述了如何使用 gdb 来定位程序中的 bug。清单 8 是一段包含 bug 的 C++ 代码。 清单 8 中的 C++ 程序试图构建 10 个链接在一起的数字框(number box),例如: 图 1. 一个包含 10 个链接在一起的数字框的列表 然后试图从这个列表中逐个删除数字框。 编译并运行这个程序,如下所示: 清单 9. 编译并运行这个程序 # g++ -g -o gdbtest1 gdbtest1.cpp # ./gdbtest1 Number Box "0" created Number Box "1" cre

31、ated Number Box "2" created Number Box "3" created Number Box "4" created Number Box "5" created Number Box "6" created Number Box "7" created Number Box "8" created Number Box "9" created list created Number Box "9" deleted Segmentation fault 正如您可以看到的一样,这个程序会导致段错误。调用 gdb 来看一下这个问题,如下所示

32、 清单 10. 调用 gdb # gdb ./gdbtest1 GNU gdb 6.2.1 Copyright 2004 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to

33、 see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "ppc-suse-linux"...Using host libthread_db library "/lib/tls/libthread_db.so.1". (gdb) 您知道段错误是在数字框 "9" 被删除之后发生的。执行 run 和 where 命令来精确定位段错误发生在程序中的什么位置。 清单 11. 执行 run

34、 和 where 命令 (gdb) run Starting program: /root/test/gdbtest1 Number Box "0" created Number Box "1" created Number Box "2" created Number Box "3" created Number Box "4" created Number Box "5" created Number Box "6" created Number Box "7" created Number Box "8" created Nu

35、mber Box "9" created list created Number Box "9" deleted Program received signal SIGSEGV, Segmentation fault. 0x10000f74 in NumBox::GetNext (this=0x0) at gdbtest1.cpp:14 14 NumBox*GetNext() const { return Next; } (gdb) where #0 0x10000f74 in NumBox::GetNext (this=0x

36、0) at gdbtest1.cpp:14 #1 0x10000d10 in NumChain::RemoveBox (this=0x10012008, item_to_remove=@0xffffe200) at gdbtest1.cpp:63 #2 0x10000978 in main (argc=1, argv=0xffffe554) at gdbtest1.cpp:94 (gdb) 跟踪信息显示这个程序在第 14 行 NumBox::GetNext (this=0x0) 接收到一个段错误。这个数字框上 Next 指针的地址是 0x0,这对于一

37、个数字框来说是一个无效的地址。从上面的跟踪信息可以看出,GetNext 函数是由 63 行调用的。看一下在 gdbtest1.cpp 的 63 行附近发生了什么: 清单 12. gdbtest1.cpp 54 } else { 55 temp->SetNext (current->GetNext()); 56 delete temp; 57

38、 temp = 0; 58 return 0; 59 } 60 } 61 current = 0; 62 temp = current; 63 current = current->GetNext(); 64 } 65

39、 66 return -1; 第 61 行 current=0 将这个指针设置为一个无效的地址,这正是产生段错误的根源。注释掉第 61 行,将其保存为 gdbtest2.cpp,然后编译并重新运行。 清单 13. 再次运行程序(gdbtest2.cpp) # g++ -g -o gdbtest2 gdbtest2.cpp # ./gdbtest2 Number Box "0" created Number Box "1" created Number Box "2" created Number Box "3"

40、 created Number Box "4" created Number Box "5" created Number Box "6" created Number Box "7" created Number Box "8" created Number Box "9" created list created Number Box "9" deleted Number Box "0" deleted 这个程序现在可以成功完成而不会出现段错误了。然而,结果并不像我们预期的一样:程序在删除 Number Box "9"之后删除了 Number Box "0",而不像

41、我们期望的一样删除 Number Box "8,"。使用 gdb 再次来看一下。 清单 14. 再次使用 gdb 进行查看 # gdb ./gdbtest2 GNU gdb 6.2.1 Copyright 2004 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under

42、 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 "ppc-suse-linux"...Using host libthread_db library "/lib/tls/libthread_db.so.1". (gdb) break 94 if i==8 Breakpoint 1 at 0x

43、10000968: file gdbtest2.cpp, line 94. (gdb) run Starting program: /root/test/gdbtest2 Number Box "0" created Number Box "1" created Number Box "2" created Number Box "3" created Number Box "4" created Number Box "5" created Number Box "6" created Number Box "7" created Number Box "8" cre

44、ated Number Box "9" created list created Number Box "9" deleted Breakpoint 1, main (argc=1, argv=0xffffe554) at gdbtest2.cpp:94 94 list ->RemoveBox(i); 您可能希望找出为什么这个程序删除的是 Number Box 0,而不是 Number Box 8,因此需要在您认为程序会删除 Number Box 8 的地方停止程序。设置这个断点:break 94 if i==8,可以在 i 等于 8

45、时在第 94 行处停止程序。然后单步跟踪到 RemoveBox() 函数中。 清单 15. 单步跟踪到 RemoveBox() 函数中 (gdb) s 38 NumBox *temp = 0; (gdb) s 40 while (current != 0) { (gdb) print pointer $1 = (NumBox *) 0x100120a8 (gdb) print *pointer $2 = {Num = 0, Nex

46、t = 0x0} (gdb) 指针早已指向了 Number Box "0",因此这个 bug 可能就存在于程序删除 Number Box "9" 的地方。要在 gdb 中重新启动这个程序,请使用 kill 删除原来的断点,然后添加一个 i 等于 9 时的新断点,然后再次运行这个程序。 清单 16. 在 gdb 中重新启动程序 (gdb) kill Kill the program being debugged? (y or n) y (gdb) info break Num Type Disp Enb Address

47、 What 1 breakpoint keep y 0x10000968 in main at gdbtest2.cpp:94 stop only if i == 8 breakpoint already hit 1 time (gdb) delete 1 (gdb) break 94 if i==9 Breakpoint 2 at 0x10000968: file gdbtest2.cpp, line 94. (gdb) run Starting program: /root/test/gdbtest2 Number

48、Box "0" created Number Box "1" created Number Box "2" created Number Box "3" created Number Box "4" created Number Box "5" created Number Box "6" created Number Box "7" created Number Box "8" created Number Box "9" created list created Breakpoint 2, main (argc=1, argv=0xffffe554) at gdbte

49、st2.cpp:94 94 list ->RemoveBox(i); (gdb) 当这一次单步跟踪 RemoveBox() 函数时,要特别注意 list->pointer 正在指向哪一个数字框,因为 bug 可能就在于 list->pointer 开始指向 Number Box "0" 的地方。请使用 display *pointer 命令来查看,这会自动显示这个函数。 清单 17. 使用 display *pointer 命令进行监视 Breakpoint 2, main (argc=1, arg

50、v=0xffffe554) at gdbtest2.cpp:94 94 list ->RemoveBox(i); (gdb) s NumChain::RemoveBox (this=0x10012008, item_to_remove=@0xffffe200) at gdbtest2.cpp:37 37 NumBox *current = pointer; (gdb) display *pointer 1: *this->pointer = {Num = 9, Next = 0x10012098} (gdb) s

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2025 宁波自信网络信息技术有限公司  版权所有

客服电话:4009-655-100  投诉/维权电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服