`
bugtags
  • 浏览: 30185 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

13 年的 Bug 调试经验总结

Bug 
阅读更多

 

在《Learning From Your Bugs》一文中,我写了关于我是如何追踪我所遇到的一些最有趣的bug。最近,我回顾了我所有的194个条目(从13岁开始),看看有什么经验教训是我可以学习的。下面是我总结的最重要的经验教训,包括编码,测试和调试三个方面。

Alt text

编码

下面这些都是我经历过的会导致难点bug的问题:

1.事件顺序。在处理事件时,提出下列问题会很有成效:事件可以以不同的顺序到达吗?如果我们没有接收到此事件会怎么样?如果此事件接连发生两次会怎么样?哪怕通常不会发生,但系统(或交互系统)其他部分的bug可能会导致事件发生呢。

2.过早。这是第一点“事件顺序”的一个特例,但它确实会引起一些棘手的bug,因此我把它单独拎出来说明。例如,如果信令消息在配置和启动程序完成之前就被过早接收,那么可能就会有很多奇怪的行为发生。另一个例子:连接在被放进空闲列表之前就被标记为down。在调试这类问题时,我们总是假定在空闲列表中的时候连接被设置为down(但当时为什么不把它放到列表外面呢?)。这是我们思考的不足,没有考虑到有时候事情会过早发生。

3.悄无声息的故障。一些最难跟踪的bug有部分是由那些静静失败并扩展而不是抛出错误的代码所导致的。例如,没有检查代码却返回错误的系统调用(如bind)。又如:解析代码在它遇到错误元素的时候只是返回而非抛出错误。在错误状态中持续了一段时间的调用,会使调试变得更难。最好一旦检测到故障就返回错误。

4.If。有若干条件的if语句,if (a 或 b) ,特别是当有链接的时候, if (x) else if (y),都给我引发了很多bug。即使if语句在概念上很简单,但当有多个条件要跟踪的时候依然很容易出错。这些天,我尝试重写代码使之更简单,以避免处理复杂的if语句。

5.Else。有一些bug是因为没有正确考虑到如果条件为false时会发生什么而引起的。几乎在所有的情况下,都应该有一个else部分来应对每一条if语句。此外,如果你在if语句的分支中设置变量,那么或许你在另一个分支中也要设置。与此种情况相关的是标记被设置的情况。只添加用于设置的标记的条件不难,但是很容易忘了添加当标记应该再次重置时的条件。留下一个永远设置的标志可能会导致之后接连不断的bug。

6.改变假设。许多一开始最难预防的bug是因为改变了假设所造成的。例如,在开始时,可能每天只有一个客户事件。于是很多代码是在这样的假设下写下的。但是后来,设计改变了,允许每天有多个客户事件了。发生这种情况时,很难改变新设计影响到的所有情况。找到关于改变的所有显式依赖关系不难,难的是要找到所有隐性依赖于旧的设计的情况。例如,可能会有获取给定某一天所有客户事件的代码。其中的隐含假设是结果集永远不会超过客户的数量。关于这方面的问题我也没有很好的策略方法,如果各位有的话,还请不吝赐教。

7.日志记录。可视化程序做什么至关重要,特别是当逻辑很复杂的时候。确保补充足够多的(但不要太多)日志记录,这样你就可以说明为什么程序要这么做。如果一切正常,那也没关系,但要是有问题发生,你会很庆幸自己添加了这些日志。

测试

作为一个开发人员,直到要测试了我才会去处理功能。至少,这意味着每一行新的或改变了的代码行至少已经被执行过一次。此外,单元测试和功能测试都很不错,但还不够。新的功能也必须进行测试,并在类似于产品的环境中探索。只有这样,我才能说我完成了一个功能。下面是我经历过的bug所教会我的关于测试的一些重要的经验教训:

8.零和null。如果可行的话,确保总是用零和null来测试。对于字符串,这意味着要测试长度为零的字符串以及字符串为null两种情况。又如:测试TCP连接的断开,要在发送数据给它发送之前。不使用这些组合方法测试是导致bug出现的首位原因。

9.添加和删除。通常,新的功能包括能够添加新的配置到系统中——例如,一个用于手机号码转换的新的配置文件。测试它能否添加新的配置文件是很自然的。但是,我发现我们很容易忘记去测试删除配置文件是不是同样ok。

10.错误处理。处理错误的代码往往是难以测试的。最好有能检查错误处理代码的自动测试,但有时这是不可能的。我有时会使用的一招是临时修改代码,使得错误处理代码运行起来。要做到这一点最简单的方法是反转if语句——例如,从if error_count > 0改成error_count == 0。另一个例子是拼错数据库列名,从而导致期望的错误处理代码运行。

11.随机输入。通常,揭露bug测试的一种测试方法是使用随机输入。例如,H.323协议的ASN.1解码使用二进制数据操作。通过发送随机字节去解码,我们发现了解码器中的几个bug。另一个例子是用测试呼叫来生成脚本,此时呼叫持续时间,接听延迟,第一方挂断等等都是随机生成的。这些测试脚本会暴露许多bug,特别是一起发生的事件会产生并拢干扰。

12.检查不应该发生的动作。通常测试包括检查期望动作是不是发生了。但我们很容易忽视相反的情况——忘记检查不应该发生的动作是不是的确没有发生。

13.拥有工具。我创建了自己的小工具,以使得测试更加简单。例如,当我用VoIP SIP协议工作时,我写了一个能够用正是我想要的标题和值回复的小脚本。这个工具使得测试很多边界情况变得容易起来。另一个例子是可以进行API调用的一个命令行工具。通过启动逐渐添加所需小功能,我得到了一些非常有用的工具。自己写工具的好处是,我得到的正是我想要的。

在测试中发现所有的bug,那绝对是不可能的。有一个案例中,我更改了数字相关性的处理,数字由两个部分组成:路由地址前缀(通常是不变的),以及从000到999动态分配的数字。问题在于当找到相关性时,动态分配的数字的第一个数字会在呈现在表格中之前遭到误删。也就是说637变成了37。这意味着,到100之前它都是可以工作的,因此,前面100个电话是正常的,但是接下来的900个都是失败。所以,除非我在重新启动之前能够测试超过100次(事实是我没有),否则我在测试时就不会发现这个问题。

调试

14.讨论。帮助我最多的调试技术是与同事讨论问题。通常情况下,只是和同事说明问题,就会让我意识到问题的症结。此外,即使他们不是很熟悉有问题的代码,他们也往往能提出一些好点子。与同事讨论在处理最难的bug时特别有效。

15.密切关注。通常,如果调试问题花了很长时间,往往是因为我做了错误的假设。例如,我认为问题发生在某一方法中,但事实却是它甚至从来没有到达那个方法。或者,被抛出的异常不是我以为的那个。或者,我认为软件的最新版本上正在运行,但其实是一个旧版本。因此,一定要核实细节,而不是假设。人们更容易看到自己希望看到的东西,而不是事实。

16.最近的变化。当曾经可以正常工作的东西停止工作,那么这通常是因为最近改变的东西所导致的。在一个案例中,最近的改变只是日志记录,但是日志中的错误却导致了一个更大的问题。为了更容易找到这种回归,承认不同的提交会导致不同的变化,以及清楚说明这些更改会有所裨益。

17.相信用户。有时,当用户报告问题的时候,我的本能反应是,“这是不可能的。一定是他们做错了什么事”。但我学会了不再用这种方式去回应。更多的时间,事实往往证明,他们所报告的的确是实际发生的情况。因此,这些天,我开始接受他们所报告的内容的表明价值。当然,我依然会仔细检查一切是否被正确地设置等等。我见过很多这样的情况,让我明白,因为不寻常的配置或意料之外的用法而导致不可思议的事情的发生,而我默认的假设是,他们是正确的,程序是错误的。

18.测试修复。如果bug修复已准备就绪,那就必须进行测试。首先在修复前运行代码,并观察该bug。然后应用修复并重复测试案例。到此为止错误行为应消失。遵循这些步骤可以确保它确实是一个bug,并且此次修复的确可以解决这个问题。简单而有必要。

其他观察结果

在这13年来我一直在跟踪我所遇到的最棘手的bug,很多事情由此而改变。我工作过小的嵌入式系统,大的电信系统以及基于web的系统。我使用过C ++,Ruby,Java和Python。在工作于C++时所遇到的几类bug已经完全消失,像堆栈溢出,内存损坏,字符串问题和某种形式的内存泄漏。

其他问题,如循环错误和边界情况,我看到的要少得多。但是,这并不意味着那里没有bug。这篇文章中的经验教训旨在帮助减少编码,测试和调试三个阶段的bug。如果大家有什么有用的预防和发现bug的技术方法,欢迎不吝指导。

译文链接:http://www.codeceo.com/article/13-years-bug.html
英文原文:Lessons From 13 Years of Bugs
翻译作者:码农网 – 小峰

 

分享到:
评论

相关推荐

    13年的 Bug 调试经验总结

    我将这13年的经验进行了总结,希望能对其他从事软件开发的同僚有所裨益。 首先,在编码层面,我认识到了事件顺序理解错误是导致bug的常见原因。编码过程中,理解系统事件的顺序是至关重要的,它要求我们在编写代码...

    十年嵌入式码农的 Bug 调试经验谈

    总结起来,嵌入式码农在进行bug调试时需要对事件顺序、假设条件、if语句的编写、无声故障的处理、日志记录等方面保持敏感和警觉。同时,了解物联网及其关键技术的应用,可以帮助嵌入式开发者更好地理解系统设计的...

    排bug的经验总结

    ### 排除Bug的经验总结 在软件开发过程中,排除Bug是一项极为重要的工作,它直接影响到产品的质量和用户体验。本文将从几个方面介绍高效排除Bug的方法与经验。 #### 代码审查(Code Review) **代码审查**是一种...

    WiFi产品射频电路调试经验.pdf

    本文档总结了Wi-Fi产品开发过程中的射频调试经验,记录并描述了在实际项目开发中遇到并解决问题的过程。作者认为,Debug过程用的都是最简单的基础知识,如果能够对RF的基础知识有极为深刻的理解,相信所有的Bug解...

    Qt creator 调试器

    **Qt Creator 调试器详解** 在软件开发过程中,调试是不可或缺的一环,它能够帮助开发者找到并修复代码中的错误。...因此,无论是初学者还是经验丰富的开发者,都应该掌握这些调试技巧,以提升自己的编程技能。

    VC调试资料全

    2. **vc调试经验总结**: 这篇文章可能包含了作者在实际项目中积累的调试经验,包括常见错误的识别、疑难问题的解决策略,以及提高调试效率的方法。这些实战经验对于新手和有经验的开发者都有很大的参考价值。 3. ...

    软件调试,很不错的书

    对于开发者来说,这些内容是非常实用的,因为良好的调试能力可以显著提高工作效率,减少bug的出现,并促进软件质量的提升。 首先,我们可以期待书中会讨论基础的调试概念,如错误类型(运行时错误、编译错误和逻辑...

    Windows高级调试 英文 pdf 源码 符号文件 pdb 完整版

    调试不仅仅是修复代码中的bug,它还涉及到对系统深层次的了解和对操作系统的深入分析。本书通过介绍高级调试技术,帮助读者在遇到棘手的问题时能够有条不紊地进行诊断和修复。 书中的源码部分是一大亮点。它提供了...

    CSDN VC编程经验总结

    《CSDN VC编程经验总结》是一本专为VC++开发者编写的实用指南,它汇聚了CSDN社区内众多编程高手的实战经验和技巧。这本书不仅涵盖了基础的VC++编程概念,还包括了许多深入的技术细节,旨在帮助读者在实际开发过程中...

    WiFi产品射频电路调试经验谈(2).pdf

    本文档总结了作者一年半以来的一些射频电路调试经验,记录的是作者在实际项目开发中遇到并解决问题的过程。作者希望通过这份文档与大家分享这些经验,帮助大家在工作中避免类似的错误。 在调试WiFi产品射频电路时,...

    《软件调试》完整版1 第1-200页0张奎银(附件太大,分开上传)

    张奎银本人在这一领域拥有超过十年的工作经验,书中的内容也是对他个人经验的总结和提升。 最后,为了帮助读者更好地理解软件调试的实践和原理,书中提供了大量的实例和案例分析,这些实例和案例贯穿全书,旨在展示...

    _程序调试思想与实践

    总的来说,程序调试是每个开发者必备的技能,它需要理论与实践相结合,不断探索和积累经验。只有深入理解调试的思想,熟练掌握调试技巧,才能在遇到问题时游刃有余,为高质量的软件开发保驾护航。

    调试九法-读书笔记.pdf

    作者华雄根据多年的调试经验,总结出了一系列的调试方法和原则,这些方法和原则对于IT行业的技术工程师来说是非常宝贵的知识。在本书的读书笔记中,我们可以提炼出如下知识点: 1. 理解系统:调试的第一步是彻底...

    javascriptt脚本调试器

    无论你是新手还是经验丰富的开发者,都应该学会善用这些调试工具,以便更好地理解和改进你的JavaScript代码。通过不断地实践和学习,你可以更深入地了解JavaScript的运行机制,编写出更高效、更稳定的代码。

    低级bug耗费12小时Fix

    ### 低级bug耗费12小时Fix:案例分析与经验总结 #### 概述 本文主要探讨一个关于软件开发中的低级bug排查案例,该bug虽然简单却导致了一个原本简单的程序耗时超过12小时才得以修复。通过深入分析这个案例,我们...

    程序调试思想与实践

    同时,通过实践,不断总结经验教训,形成自己的调试方法论,也是成为优秀程序员的必经之路。 总之,程序调试思想与实践是以Bug为中心的探索过程,它融合了理论知识、实践经验和技术工具。通过以上所述的方法和技巧...

    gdb调试器详解

    ### gdb调试器详解 #### 一、gdb概述与重要性 gdb(GNU Debugger)是一种功能强大的开源调试工具,广泛应用于Unix/Linux平台上的...无论是初学者还是经验丰富的开发者,掌握gdb都将极大地提高调试效率和代码质量。

    如何写有效的软件测试Bug报告

    本文基于Kelly Whitmill的专业经验,总结了一系列撰写有效Bug报告的方法。 #### 二、为何撰写有效的Bug报告至关重要 - **减少二次缺陷率**:通过提供详尽的缺陷描述,可以避免开发人员在修复过程中引入新的问题。 -...

    2007年QA典型百大MISSBUG总结

    2007年的总结可能包含了这些分类的典型例子,分析了各类BUG产生的原因和解决方案。 2. **错误报告**:有效的BUG报告包括错误的详细描述、重现步骤、影响的系统环境以及期望的结果。报告的质量直接影响到问题的定位...

    如何有效写bug报告

    Kelly Whitmill拥有18年的软件测试经验,曾在多个公司担任团队负责人,擅长利用有限资源进行高效的测试工作。以下内容将详细介绍撰写有效缺陷报告的关键要素。 #### 二、为什么需要有效撰写缺陷报告 有效撰写缺陷...

Global site tag (gtag.js) - Google Analytics