本文的copyleft归gfree.wind@gmail.com所有,使用GPL发布,可以自由拷贝,转载。但转载请保持文档的完整性,注明原作者及原链接,严禁用于任何商业用途。
作者:gfree.wind@gmail.com
博客:linuxfocus.blog.chinaunix.net

作为程序员,调试是一项很重要的基本功。调试的技巧和水平,直接决定了解决问题的时间。一般情况下,GDB的基本命令已经足以应付大多数问题了。但是,对于有些问题,还是需要更高级一些的命令。今天介绍一下checkpoint。
有一些bug,可能很难复现,当好不容易复现一次,且刚刚进入程序的入口时,我们需要珍惜这个来之不易的机会。如果只使用基本命令的话,对于大部分代码,我们都需要使用step来步进。这样无疑会耗费大量的时间,因为大部分的代码可能都没有问题。可是一旦不小心使用next,结果恰好该语句的函数调用返回出错。那么对于这次来之不易的机会,我们只得到了部分信息,即确定问题出在该函数,但是哪里出错还是不清楚。于是还需要再一次的复现bug,时间就这样浪费了。
所以,对于这种问题,就是checkpoint大显身手的时候。先看一下GDB关于checkpoint的说明:
On certain operating system(Currently, only GNU/Linux), GDB is able to save a snapshot of a program's state, called a checkpoint and come back to it later.
Returning to a checkpoint effectively undoes everything that has happened in the program since the checkpoint was saved. This includes changes in memory, register, and even(within some limits) system state. Effectively, it is like going back in time to the moment when the checkpoint was saved.
也就是说checkpoint是程序在那一刻的快照,当我们发现错过了某个调试机会时,可以再次回到checkpoint保存的那个程序状态。
举例说明一下:
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. static int func()
  4. {
  5. static int i = 0;
  6. ++i;
  7. if (i == 2) {
  8. return 1;
  9. }
  10. return 0;
  11. }
  12. static int func3()
  13. {
  14. return func();
  15. }
  16. static int func2()
  17. {
  18. return func();
  19. }
  20. static int func1()
  21. {
  22. return func();
  23. }
  24. int main()
  25. {
  26. int ret = 0;
  27. ret += func1();
  28. ret += func2();
  29. ret += func3();
  30. return ret;
  31. }
当我们执行这个程序时,发现程序返回1,不是期望的成功0。于是开始调试程序,由于函数调用的嵌套过多,我们没法一眼看出是main中的哪个函数调用出错了。于是在ret += func1()前,我们保存一个checkpoint。
  1. (gdb) b main
  2. Breakpoint 1 at 0x80483e0: file test.c, line 31.
  3. (gdb) r
  4. Starting program: /home/fgao/works/test/a.out
  5. Breakpoint 1, main () at test.c:31
  6. 31 int ret = 0;
  7. Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.i686
  8. (gdb) n
  9. 33 ret += func1();
  10. (gdb) checkpoint
  11. checkpoint: fork returned pid 2060.
  12. (gdb)
然后使用next步进,并每次调用完毕,打印ret的值
  1. Breakpoint 1, main () at test.c:31
  2. 31 int ret = 0;
  3. (gdb) n
  4. 33 ret += func1();
  5. (gdb) checkpoint
  6. checkpoint: fork returned pid 2060.
  7. (gdb) n
  8. 34 ret += func2();
  9. (gdb) p ret
  10. $4 = 0
  11. (gdb) n
  12. 35 ret += func3();
  13. (gdb) p ret
  14. $5 = 1
结果发现,在调用func2()调用后,ret的值变为了1。可是此时,我们已经错过了调试func2的机会。如果没有checkpoint,就需要再次从头调试了——对于这个问题从头调试很容易,但是对于很难复现的bug可就不说那么容易的事情了。
ok,使用checkpoint恢复
  1. (gdb) restart 1
  2. Switching to process 2060
  3. #0 main () at test.c:33
  4. 33 ret += func1();
  5. (gdb)
很简单,现在GDB恢复到了保存checkpoint时的状态了。上面“restart 1“中的1为checkpoint的id号,可以使用info查看。
  1. (gdb) info checkpoints
  2. * 1 process 2060 at 0x80483e7, file test.c, line 33
  3. 0 process 2059 (main process) at 0x80483f7, file test.c, line 35
从上面可以看出checkpoint的用法很简单,但是很有用。就是在平时的简单的bug修正中,也可以加快我们的调试速度——毕竟减少了不必要的重现bug的时间。

转载于:https://blog.51cto.com/tonghuix/1165828

GDB技巧:使用checkpoint解决难以复现的Bug相关推荐

  1. 每日一皮:一个难以复现的 bug ...

    往期推荐 每日一皮:史上最直观的单向循环链表,还不懂算我输! 每日一皮:当我看到Bug背后的一切...我退缩了... 每日一皮:重构时总会出现的惊喜....... 每日一皮:实习生将他的代码交给高级开 ...

  2. IOS小技巧–用runtime 解决UIButton 重复点击问题

    IOS小技巧–用runtime 解决UIButton 重复点击问题 什么是这个问题 我们的按钮是点击一次响应一次, 即使频繁的点击也不会出问题, 可是某些场景下还偏偏就是会出问题. 通常是如何解决 我 ...

  3. android8卡顿,看完就明白为什么安卓手机卡顿,这个技巧教你解决卡顿

    原标题:看完就明白为什么安卓手机卡顿,这个技巧教你解决卡顿 Android由源代码开放,所以安卓手机拥有更多的黑科技功能.很多安卓用户觉得手机卡顿,其实是没有好好利用这些神奇功能.下面笔者就为大家介绍 ...

  4. Mac使用技巧:如何解决键盘被锁的问题?

    日常使用电脑的时候,经常会遇到一开机就发现键盘什么键都按不了的情况,刚开始以为是死机,检测后发现是键盘被锁定了,是按到什么不知名的快捷键导致的?那么要怎么解决mac键盘被锁住的问题?一起看看吧! 解决 ...

  5. oracle enq ta,【案例】Oracle等待事件event enq: KO - fast object checkpoint解决办法

    [案例]Oracle等待事件event enq: KO - fast object checkpoint解决办法 时间:2016-11-03 10:11   来源:Oracle研究中心   作者:HT ...

  6. MacBook使用技巧:如何解决经常死机

    Macbook 苹果笔记本电脑经常死机的原因: 1. 系统出现问题. 2.主板有问题,主板工作不正常. 针对以上原因,建议您尝试以下方式来解决问题: 1.查看你的软件是否存在不兼容的问题.经常引起死机 ...

  7. AE技巧-有效预防/解决AE CC 2010、2017和2018字体报错问题CT generic: not ascii(83 :: 2)

    AE技巧-有效预防/解决AE CC 2010.2017和2018字体报错问题After Effects error: CT generic: not ascii (83 :: 2) 相信很多人对这个弹 ...

  8. vim 使用技巧 set paste 解决粘贴乱序问题

    vim 使用技巧 set paste 解决粘贴乱序问题

  9. 张驰咨询:质量人如何运用六西格玛培训解决难以突破的技术问题

    六西格玛是一种基于数据和统计的方法,旨在改进业务流程,提高质量和效率.作为质量人员,您可以使用这种方法来解决难以突破的技术问题,以下是六西格玛培训解决技术问题的步骤: 1.确定问题范围和定义问题 在使 ...

最新文章

  1. jquery键盘事件
  2. 一个顾客买了价值x元的商品(C语言)
  3. 提高ASP.NET首页性能的十大方法
  4. AS3.0第一个实例:(Hello World)
  5. python多个变量的for循环
  6. Hive2.1.1、Hadoop2.7.3 部署
  7. PHP处理图片导致内存溢出
  8. 完成端口可用回射服务器
  9. vscode 配置import @ 路径提示及代码智提
  10. c语言输出字母随机数,你好,怎样用c语言输出一个1到100的随机数
  11. fullAvatarEditor富头像上传编辑器
  12. 查看SQL语句执行耗费的时间
  13. Problem:跳房子
  14. Win10中安装Oracle11g
  15. 随机森林(Random Forest)算法原理
  16. linux 775和777权限有什么区别
  17. 多约束条件求最优值matlab,[MATLAB数学相关] 请教,约束条件下多元函数最小值的求解...
  18. 我的springBoot框架学习总结
  19. halt ,poweroff和shutdown 的区别
  20. Python pandas在读取csv文件时(linux与windows之间传输),数据行数不一致的问题

热门文章

  1. 在微信浏览器字体被调大导致页面错乱的解决办法
  2. 任何时候,写下一个类,一定要有三个函数
  3. [OpenGL ES 03]3D变换:模型,视图,投影与Viewport
  4. 利用PHP SOAP实现web service
  5. 自省:我为什么没有成功--对照35前务必完成的12跳
  6. PowerDesigner12对SQL2005反向工程问题.
  7. python基础 函数 (四)
  8. 【GOF23设计模式】原型模式
  9. MacosX 下GCC编译指定版本的代码
  10. vue项目如何打包扔向服务器 - Hi-Sen - 博客园