GDB调试:Linux开发人员必备技能

开篇词:Linux C/C++ 开发人员要熟练掌握 GDB 调试

大家好,我是范蠡,目前在某知名互联网旅游公司基础框架业务部技术专家组任开发经理一职。

本系列课程的主题是 Linux 后台开发的 C/C++ 调试,通俗地说就是 GDB 调试。GDB(GNU Debugger)是类 Unix(如 Linux)操作系统下的一款开源的 C/C++ 程序调试器。最初是在 1988 年由理查德 · 马修 · 斯托曼(Richard Stallman)所撰写,之后以 GNU 通用公共许可证(GNU General Public License,GNU GPL)的许可方式将软件发布,因此 GNU Debugger 是一套自由软件。发布后的 1990 年-1993 年间则由任职于 Cygnus Solutions 公司的约翰 · 吉尔摩(John Gilmore)负责后续的软件维护工作,点击这里了解其历史详情。

0.1 为什么要写这个课程

我从学生时代到进入软件开发这个行业,不知不觉已经十余年了,真是时光荏苒、光阴如梭。这些年,先后在网游公司做过游戏服务器,为上海某交易所做过金融交易系统、在金融证券公司做过股票证券交易系统和即时通讯软件、在音视频直播公司做过直播服务器,各种项目使用的服务器操作系统都是 Linux,开发语言是 C/C++ 。正如从事 Windows C/C++ 开发的一定要熟悉 Visual Studio、从事 Java 开发的要熟悉 Eclipse 或 IntelliJ IDEA、从事 Android 开发的要熟悉 Android Studio、从事 iOS 开发的要熟悉 XCode 一样,从事 Linux C/C++ 开发要熟悉 GDB。

虽然 Linux 系统下读者编写 C/C++ 代码的 IDE 可以自由选择,但是调试生成的 C/C++ 程序一定是直接或者间接使用 GDB。可以毫不夸张地说,我所做这些项目的开发和调试包括故障排查都是利用 GDB 完成的,调试是开发流程中一个非常重要的环节,因此对于从事 Linux C/C++ 的开发人员熟练使用 GDB 调试是一项基本要求

当每次有人来面试时,我会问他熟悉哪些开发工具,有些面试者对各种开发工具都不熟悉,我猜想这类应聘者应该是基本“不写代码”或者“不会写代码”的,当然面试结果也可想而知了。“工欲善其事、必先利其器”,作为一名合格的软件开发者,至少得熟悉一种软件开发工具和调试器, 而对于 Linux C/C++ 后台开发,舍 GDB 其谁。

一些初中级开发者可能想通过阅读一些优秀的开源项目来提高自己的编码水平,但是只阅读代码,不容易找到要点,或者误解程序的执行逻辑,最终迷失方向。如果能实际利用调试器去把某个开源项目调试一遍,学习效果才能更好。站在 Linux C/C++ 后台开发的角度来说,学会了 GDB 调试,就可以对各种 C/C++ 开源项目(如 Redis、Apache、Nginx 等)游刃有余。简而言之,GDB 调试是学习这些优秀开源项目的一把钥匙。下面举两个基本的例子。

  • 例子一,对于 C/C++ 这门存在多态的特性的编程语言,当用一个基类对象类型指向其子类实例,然后调用在子类中被重写(Override)的某个方法,在复杂的代码中我们很难通过肉眼去梳理清楚程序实际的执行脉络,而使用 GDB 调试的 step 命令,可以很方便地追踪程序的实际执行流。
  • 例子二,使用 GDB 可以快速方便地了解一个程序的整体结构,在分析一个开源软件的整体结构时,可以使用 GDB 先将程序跑起来,然后中断下来,使用 GDB 的 info thread 和 backtrace 命令分析程序的线程数目和调用上下文。在后面内容中,我们使用 GDB 分析 redis-server 网络通信模块的基本结构也是这个思路。

还有一类情况,那就是在实际开发中总会遇到一些非常诡异的程序异常或者问题崩溃的情况。解决这些问题很重要的一个方法就是调试,而对于 Linux C/C++ 服务来说,熟悉 GDB 各种高级调试技巧非常重要。举个例子,对于大多数由内存访问冲突导致的程序崩溃,我们都可以使用 GDB 分析产生的 core 文件来定位问题原因;另外对于一些出现几率比较低,比如一万次操作可能只会出现一个,我们可以在不修改程序代码的前提下,使用 GDB 条件断点的功能设置触发条件,最终定位和解决问题。

0.2 课程特色

  • 本课程不是人云亦云地介绍 GDB 的各个命令的用法,而是从 What、How、Why 三个角度来介绍 GDB 调试中的技巧和注意事项;所引用的示例也不是“helloworld”式的 demo,而是以时下最流行的内存数据库 Redis 为示例对象。
  • 整个课程循序渐进,从基础的调试符号原理,到 GDB 启动调试的方式,再到常用命令详解,接着介绍 GDB 高级调试技巧和一些更强大的 GDB 扩展工具,最后使用 GDB 带领读者分析 Redis 服务器端和客户端的网络通信模块。
  • 在这个课程中读者不仅可以学习到实实在在的调试技巧和网络编程知识,也可以学习到如何梳理开源软件项目结构和源码分析思路

0.3 课程介绍

调试是开发过程中一项不可或缺的工作,在 Linux 编程中,通常使用 GDB 来调试 C/C++ 程序,一个合格的 Linux C/C++ 开发人员,必须熟练使用 GDB 调试。互联网上有太多关于 GDB 的教程,基本上是人云亦云,我在 Linux 服务器开发方面从业多年,本课程将介绍 GDB 调试最常用的知识和技巧,还有一些重点和难点。

本课程分为五大部分,共计 19 篇(含开篇词)。

  • 第一部分(第01 ~ 03课)主要介绍了 Linux C/C++ 调试的一些基础知识。例如,core 文件的基础知识、GDB 调试启动进程的方法。
  • 第二部分(第04 ~ 06课)详细介绍了 GDB 常用调试命令的使用和注意事项,这里不是孤零零地介绍每个命令的使用,而是结合具体的使用实例来说明。

如果认真学习完并掌握第一部分和第二部分内容后,然后一边调试一边学习 Linux 下开源的 C/C++ 项目应该就不成问题了。

  • 第三部分(第07 ~ 08课)介绍了我在实际工作中开发 Linux 后台 C/C++ 服务时,利用 GDB 调试和排查问题使用的一些高级实用技巧,自成一套体系,如果读者仅对这部分内容感兴趣也可以单独阅读相关内容。
  • 第四部分(第09 ~ 12课)介绍了基于 GDB 的一些相关的升级版调试工具,主要内容是 CGDB 和 VisualGDBCGDB 是基于 GDB 的一款可以在调试过程中以图形化界面显示和跳转源码的开源工具,为很多觉得 GDB 自带的 list显示源码不方便的开发者带来更好的调试体验;而 VisualGDB 是 Visual Studio 的一个插件,其基于 SSH 协议和 Samba Server,有了它,读者可以利用 Visual Studio 这一强大的图形化 IDE 远程调试 Linux 机器上的程序,不必再频繁地输入各种 GDB 命令,这也为广大 Windows C/C++ 开发者想学习 Linux C/C++ 开发带来很大的方便。
  • 第五部分(第13 ~ 18课)的内容是一个完整、详尽的 GDB 实例教程,通过 GDB 调试来带领读者学习时下最流行的内存数据库 Redis 的网络通信模块代码。学完这部分内容不仅可以进一步熟悉 GDB 调试,同时还可以学习到 Redis 和网络编程相关知识。

在选择哪些程序作为 GDB 调试的教学程序时,着实让我纠结了很久。很多 GDB 教程都是人为的“造”一些实例代码,我感觉这样做有点脱离实际生产。实际项目中的代码与这种“造”出来的代码相差很大,同时程序很难调;不过实际项目中的代码,由于企业单位的保密协议要求,也不方便外传。经过慎重考虑,课程舍弃了我自己编写的几个实例代码,最终选择带领读者调试 Redis 代码。

0.4 课程寄语

本课程所讨论的知识和内容都来源于实际开发,尽量避免人云亦云和闭门造车,课程中也详细地给出了每一步的操作步骤。因此,希望广大读者能跟随课程介绍,在自己的环境中实际演练一遍,这样学习的效果会更好。当你掌握了 GDB 调试的精髓以后,将有能力进一步研究其他一些优秀的开源 Linux C/C++ 项目(如 Apache、Nginx)

最后,预祝大家学习愉快!

你可能感兴趣的:(Linux,gdb)