GDB技巧:使用checkpoint解决难以复现的Bug

简介: 本文的copyleft归gfree.wind@gmail.com所有,使用GPL发布,可以自由拷贝,转载。但转载请保持文档的完整性,注明原作者及原链接,严禁用于任何商业用途。作者:gfree.wind@gmail.com博客:linuxfocus.blog.chinaunix.net 作为程序员,调试是一项很重要的基本功。
本文的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的时间。

相关实践学习
阿里云图数据库GDB入门与应用
图数据库(Graph Database,简称GDB)是一种支持Property Graph图模型、用于处理高度连接数据查询与存储的实时、可靠的在线数据库服务。它支持Apache TinkerPop Gremlin查询语言,可以帮您快速构建基于高度连接的数据集的应用程序。GDB非常适合社交网络、欺诈检测、推荐引擎、实时图谱、网络/IT运营这类高度互连数据集的场景。 GDB由阿里云自主研发,具备如下优势: 标准图查询语言:支持属性图,高度兼容Gremlin图查询语言。 高度优化的自研引擎:高度优化的自研图计算层和存储层,云盘多副本保障数据超高可靠,支持ACID事务。 服务高可用:支持高可用实例,节点故障迅速转移,保障业务连续性。 易运维:提供备份恢复、自动升级、监控告警、故障切换等丰富的运维功能,大幅降低运维成本。 产品主页:https://www.aliyun.com/product/gdb
目录
相关文章
|
机器学习/深度学习 算法 网络架构
【CVPR2017】AOD-Net:端到端的除雾网络(原理&实操)
【CVPR2017】AOD-Net:端到端的除雾网络(原理&实操)
2634 0
【CVPR2017】AOD-Net:端到端的除雾网络(原理&实操)
|
机器学习/深度学习 分布式计算 Java
Hbase入门(二)——安装与配置
本文讲述如何安装,部署,启停HBase集群,如何通过命令行对Hbase进行基本操作。 并介绍Hbase的配置文件。 在安装前需要将所有先决条件安装完成。
1145 0
Hbase入门(二)——安装与配置
|
9月前
|
数据采集 机器学习/深度学习 DataWorks
DataWorks产品评测:大数据开发治理的深度体验
DataWorks产品评测:大数据开发治理的深度体验
372 1
|
存储 算法 数据处理
|
JSON Cloud Native 关系型数据库
云原生数据仓库操作报错合集之遇到报错 "ERROR: out of shared memory" ,该怎么办
阿里云AnalyticDB提供了全面的数据导入、查询分析、数据管理、运维监控等功能,并通过扩展功能支持与AI平台集成、跨地域复制与联邦查询等高级应用场景,为企业构建实时、高效、可扩展的数据仓库解决方案。以下是对AnalyticDB产品使用合集的概述,包括数据导入、查询分析、数据管理、运维监控、扩展功能等方面。
|
人工智能 数据挖掘 大数据
如何做好舆情大数据分析工作
舆情大数据分析是一项复杂而系统的工作,它涉及舆情监测、数据汇总和过滤分类、数据分析、结果呈现与报告撰写以及反馈等多个工作流程。因此,对于政企单位来说,如何做好舆情大数据分析工作是个难题。下面,本文就来详细为各位阐述舆情大数据分析工作内容以及如何做好舆情大数据分析工作?
311 4
|
消息中间件 关系型数据库 MySQL
SpringBoot-Kafka(生产者事务、手动提交offset、定时消费、消息转发、过滤消息内容、自定义分区器、提高吞吐量)
SpringBoot-Kafka(生产者事务、手动提交offset、定时消费、消息转发、过滤消息内容、自定义分区器、提高吞吐量)
SpringBoot-Kafka(生产者事务、手动提交offset、定时消费、消息转发、过滤消息内容、自定义分区器、提高吞吐量)
|
NoSQL MongoDB 数据库
国内唯一 阿里云荣膺MongoDB“2024年度DBaaS认证合作伙伴奖”
阿里云连续第五年斩获MongoDB合作伙伴奖项,也是唯一获此殊荣的中国云厂商。一起学习MongoDB副本集的选举机制以及可能会出现的特殊情况。
国内唯一 阿里云荣膺MongoDB“2024年度DBaaS认证合作伙伴奖”
|
算法 搜索推荐 开发者
优化Python代码执行效率的技巧与实践
提升Python代码执行效率是开发过程中的关键挑战之一。本文探讨了几种有效的优化策略,包括算法选择、数据结构优化以及代码优化技巧,帮助开发者在实际项目中提升程序性能和响应速度。
|
Python
Pygame AttributeError no attribute ‘display‘问题及其解决方法
Pygame AttributeError no attribute ‘display‘问题及其解决方法
434 4