还在断点调试?4种调试技巧让你快速定位错误!

简介: 九章算法金牌讲师、前FB资深架构师令狐冲总结了4种调试技巧,帮你高效debug。

许多同学经常把一个程序直接贴给我说:

老师,我的程序出错了,帮我看看吧。

对于这些同学的请求,我往往只能委婉的拒绝:

调试要靠自己哦~ 我帮你指出程序的错误,对于你自己一点帮助都没有。你今天先继续努力debug,明天要是还不能解决,我就帮你看看。

虽然大部分的人最终都能靠自己找到错误,但是学会好的调试技巧,确实能够起到事半功倍的刷题效果。

于是我总结了四种我自己常用的在刷题过程中的调试技巧,希望可以帮助到大家:

技巧1: 打印中间结果

依赖于IDE的断点调试,是十分浪费时间的一种调试方法。而且在面试中,你是基本没有断点调试的机会的(因为很多公司是白板写题,不会提供给你IDE)。

事实上在实际的工作中,你也很少能够有机会去进行断点调试,比如你进行的是 Web 开发,你只能想方设法的在代码中打印一些 Log,然后根据 Log 去分析出错的原因。你平时用 IDE 写代码,就十分容易养成这种断点调试的“坏习惯”。一个更好的方式,是使用打印中间结果的方式。以 LintCode 上的 Clone Graph 为例子:

image.png

LintCode 支持自己出测试数据进行测试的模式,点到“Testcase” 这个 tab之后,输入测试数据,点 Run Code。你的程序中的输出也会被显示在 Output 中。我们看到 代码中 第22行到27行,是在打印一个中间结果,这个中间结果就是在使用了 bfs 算法之后,从一个点出发,找到的所有的图中其他节点。这样我们就可以迅速验证,代码出错到底是因为 BFS 写错了,还是因为其他的部分写错了。

使用这种调试方法的另外一个好处是,你很自然的希望你的程序可以“分阶段”输出一些中间结果,这种分阶段处理的方式,也是我们在课上经常强调的,把大问题变成小问题,然后逐个击破的编程思想。养成这种编程习惯之后,可以非常有效的帮助你在写程序的时候,就避免掉错误。

技巧2: 一行一行改成参考程序

九章的官网 中有 LC 完整的参考程序库,其中 Java 程序的一部分代码是我自己亲自编写的,具备较高的质量和参考价值。很多题目也给了多种不同的解法。比如 Binary Tree Level Order Traversal 这一题,给出了三种 BFS 的参考程序和 1个 DFS的参考程序。通常来说很多题目,你不仅仅需要掌握其中一种方法,而是需要掌握这个题所有的解决办法。

有不少同学经常会来问我:

老师,我的代码和参考程序一样啊,为什么还是不对?

这种时候,我通常建议他们,将自己的代码,一行一行的改成参考程序。这样,当他们发现哪一行代码不一样的时候,就自然定位到了错误。

举一个例子,就以 Binary Tree Level Order Traversal 为例,宽度优先搜索算法(BFS)是面试必须掌握的一种算法。来看看下面这个有错误的代码(请花3分钟阅读一下,并找出错误所在):

image.png

从程序思想上来看,好像并没有什么错。很难直接发现有什么问题。与参考程序逐行对比之后会发现,错误发生在第14行。

参考程序中,写法是:

image.png

和上面的程序写法是:

image.png

这两种写法存在巨大区别,原因是在循环体内部,我们会不断往 queue 中放东西,这导致了queue.size() 的值是不断变化的。而没有起到我们只想循环当前这一层所有点的功能。

通过对这个程序逐行对比,我们能够马上学会如下的知识点:

  1. for循环中间的判断语句,在循环体的每一次循环中都会被重复执行,而不是在一开始就确定好执行多少次。
  2. 为了做到BFS的分层遍历,需要先把 size 取出来,再 for循环这个size,这是BFS分层遍历中最关键的一句话。

技巧3: 给小熊讲程序

这个技巧,是我曾经参加高中生算法竞赛的时候,一位算法竞赛国家队的前辈教我的。

当时我的算法水平可能已经还不错了,但是代码质量很差,很容易写出有bug的代码。这位前辈告诉我,可以放一只 “小熊” 在你的电脑旁边,一旦程序出错了。就对着这只小熊讲你的整个代码是怎么解决问题的。

因为是给小熊讲,所以你可以把它当作什么都不懂,于是需要更加仔细的去讲述你代码中每个细节,所以你需要一行一行的讲,甚至连为什么你要用 ArrayList 而不用 int[] 都要讲得清清楚楚。讲着讲着,你就有可能突然发现你的错误所在了。

这个技巧的意义在于,你在写代码的时候,脑子里可能想着一个事情,但是打出来的代码,可能是另外一回事儿。或者你脑子里想着有3个条件需要判断,但是打的时候,漏掉了一个。当你把代码重新讲一遍的时候,事实上是在重新整理你的逻辑,查漏补缺。这样很容易就能够发现你的错误。

技巧4: 必杀,重写一遍

大部分的bug,其实都是 typo。比如:

  1. 大于符号和小于符号打反了
  2. <= 写成了 <
  3. 本来要写一句话干什么来着但是后来写着写着忘记了
  4. if 后面忘了加 else
  5. for 循环后面忘了加括号,导致代码跑到了循环体之外
  6. 变量名打错:for(int j=0;i

诸如此类,不胜繁举。重新写一遍代码, 往往都能 fix 这些问题。

尾声

调试是在你出现 BUG 的时候,才需要做的事情。大家平时应该尽量去练习的是不要写出有BUG的代码。

这的确很难,但是你应该以此为训练目标,在你在 LintCode 上点击 “Submit” 之前,尽量的做到已经检查过自己的代码,不要过分依赖于 Online Judge帮你判断你的代码是否有错,更加不要依赖于本地 IDE 的断点调试功能。在 LintCode 这个界面(登陆后可见),可以看到自己提交的指标:

image.png

这个指标非常的重要,他是判断你的代码是否 Bug Free 的重要参考数据。如果你最近一个月内的这个数据在 3 以内,那么说明你的代码具备非常高的质量,不太容易出bug。如果在3-4之间,说明,还可以有所提高。如果在4以上,说明,你的代码质量比较糟糕了。

九章算法 ,国内&硅谷一线工程师在线直播授课,已经帮助30000+人成功拿到心仪offer。

相关文章
|
存储 NoSQL 安全
【C++调试】深入探索C++调试:从DWARF到堆栈解析
【C++调试】深入探索C++调试:从DWARF到堆栈解析
808 1
|
7月前
|
Kubernetes 网络协议 API
在k8s集群中解决master节点与node通信问题
整个排查和解决流程需要综合应用以上方法,以及根据具体情况调整排查顺序或应用其他技术细节。为保证解决方案的实用性和有效性,还需紧跟Kubernetes社区的最新动态和最佳实践。在实际操作过程中,应记录所采取的步骤和观察到的系统响应,以便在遇到类似问题时能够快速定位和解决。
522 8
|
Shell 开发工具 git
上传文件到gitee(小白都能学会)
上传文件到gitee(小白都能学会)
5228 13
|
Java 程序员 PHP
01 入门PHP就来我这-安装phpstudy
路老师的PHP入门教程,带你从零开始学习PHP。首先下载并安装phpStudy,接着配置域名和端口,最后创建并运行第一个PHP文件。内容详实,适合初学者。
302 3
01 入门PHP就来我这-安装phpstudy
|
开发工具 git
git clone避坑的万能步骤
git clone避坑的万能步骤
2993 1
|
人工智能
通义千问大模型价格直线下调,优惠升级!更有新用户限时免费领取3600万额度!
通义大模型全线9款直降,最高达97%,阿里云MaaS(模型即服务)让推理成本大幅降低,加速AI应用爆发。 即刻登录阿里云百炼官网https://bailian.aliyun.com调用体验,新用户免费限时赠送3600万tokens!
3061 3
|
图形学 索引
【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏1(附项目源码)
【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏1(附项目源码)
751 0
|
JavaScript 前端开发 算法
【Node.js 版本过高】运行前端时,遇到错误 `Error: error:0308010C:digital envelope routines::unsupported`
【Node.js 版本过高】运行前端时,遇到错误 `Error: error:0308010C:digital envelope routines::unsupported`
9260 0
|
NoSQL IDE Unix
Windows下如何使用和调试GDB
Windows下如何使用和调试GDB
Windows下如何使用和调试GDB
|
SQL 关系型数据库 MySQL
MySQL必看表设计经验汇总-下(精华版)
MySQL必看表设计经验汇总-下(精华版)
399 1