0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Bug调试经验总结

传感器技术 来源:EDN电子技术设计 作者:EDN电子技术设计 2021-05-10 14:17 次阅读

这十年来我做过小的嵌入式系统,大的电信系统以及基于web的系统。使用过C ++,Ruby,JavaPython等。这篇文章中的经验教训旨在帮助减少编码,测试和调试三个阶段的bug。

下面这些都是我经历过的会导致难点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所教会我的关于测试的一些重要的经验教训:

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

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

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

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

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

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

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

调试

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

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

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

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

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

其他观察结果

现在工作于C++时所遇到的几类bug已经完全消失,像堆栈溢出,内存损坏,字符串问题和某种形式的内存泄漏。

其他问题,如循环错误和边界情况,我看到的要少得多。但是,这并不意味着那里没有bug。如果大家有什么有用的预防和发现bug的技术方法,欢迎留言。

作为过来人,最后还想说几句心灵鸡汤:

1、分享第一条经验:“学历代表过去、能力代表现在、学习力代表未来。”

2、一定要确定自己的发展方向,并为此目的制定可行的计划。

3、软件开发团队中,技术不是万能的,但没有技术是万万不能的!

4、详细制定自己软件开发专业知识学习计划,并注意及时修正和调整(软件开发技术变化实在太快)。

5、书籍是人类进步的阶梯,对软件开发人员尤其如此。

6、不要仅局限于对某项技术的表面使用上,哪怕你只是偶尔用一、二次。

7、在一种语言上编程,但别为其束缚了思想。“代码大全”中说:“深入一门语言编程,不要浮于表面”。

8、养成总结与反思的习惯,并有意识地提炼日常工作成果,形成自己的个人源码库、解决某类问题的通用系统体系结构、甚至进化为框架。

9、理论与实践并重,内外双修。

10、心态有多开放,视野就有多开阔。

11、尽量参加开源项目的开发、或者与朋友共同研制一些自己的产品,千万不要因为没有钱赚而不做。

12、书到用时方恨少,不要将自己的知识面仅仅局限于技术方面。

总结与反思:

(a)不要去做技术上的高手,除非你的目标如此。

(b)提高软件知识和技术只是问题的表面,本质是要提高自己认识问题、分析问题、解决问题的思想高度。软件专业知识的很多方法和原理,可以很容易地延伸、应用到生活的其它方面。

(c)在能胜任工作的基础上,立即去涉猎其它领域的专业知识,丰富自己的知识体系、提高自己的综合素质,尤其是那些目标不在技术方面的朋友。

责任编辑:lq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 解码器
    +关注

    关注

    9

    文章

    1144

    浏览量

    40801
  • 嵌入式
    +关注

    关注

    5087

    文章

    19148

    浏览量

    306182
  • TCP
    TCP
    +关注

    关注

    8

    文章

    1374

    浏览量

    79147

原文标题:嵌入式大牛10年调Bug经验总结

文章出处:【微信号:WW_CGQJS,微信公众号:传感器技术】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    光伏系统施工问题的注意事项

    随着太阳能发电技术的日益成熟,光伏系统的应用和安装变得越来越普遍。建设一座安全高效的光伏电站,离不开高质量的施工。通过近几年的现场维护和经验总结,本期小课堂将为大家分享一些光伏施工中的常见问题。
    的头像 发表于 12-26 14:05 208次阅读

    KiCon 演讲回顾(十五):提交 Kicad Bug

    “ Wayne Stambaugh 分享了如何提升 KiCad 用户和开发者体验的关键一环:报告KiCad Bug。 ” 完整的演讲视频在这里: KiCad的使命 KiCad旨在为专业电子设计师提供
    的头像 发表于 12-11 09:09 171次阅读
    KiCon 演讲回顾(十五):提交 Kicad  <b class='flag-5'>Bug</b>

    电源环路快速调试理论与经验

    电源环路快速调试理论与经验 在工程实际应用中,下图所示有源补偿网络最常见: 有源补偿网络(一)的简图如下所示: 以上均属于有源超前-滞后补偿网络,其传递函数、零点和极点的推导公式详见徐德鸿教授所著
    的头像 发表于 11-28 10:59 292次阅读
    电源环路快速<b class='flag-5'>调试</b>理论与<b class='flag-5'>经验</b>

    烟花爆竹企业电瓶车使用安全管理的当前状况与管理对策

    本文以四川省某烟花爆竹企业因电瓶车使用不当引发的燃爆事故为实例,通过具体案例分析、经验总结及文献参考等多种方法,综合探讨了烟花爆竹企业在使用电瓶车过程中面临的问题,并提出了相应的安全管理对策与措施。
    的头像 发表于 10-28 10:37 394次阅读
    烟花爆竹企业电瓶车使用安全管理的当前状况与管理对策

    Linux日志管理经验总结

    日志内容,合理的日志内容(日志锚点,内容格式,等)可以为应用服务的执行记录、问题排查提供最有力的帮助。
    的头像 发表于 10-24 17:36 232次阅读

    业务复杂度治理方法论--十年系统设计经验总结

    复杂度量公式        子模块的复杂度cp乘以该模块对应的开发时间权重值tp,累加后得到系统的整体复杂度C 这里的子模块复杂度 cp是一个经验值 需要注意:如果一个子系统特别复杂,但是很少使用及修改,也不会对整体复杂度造成太大影响。例:spring框架内部代
    的头像 发表于 09-05 14:11 1019次阅读
    业务复杂度治理方法论--十年系统设计<b class='flag-5'>经验总结</b>

    stm32H7 HAL库中存在的bug

    stm32H7 hal 库里面的以太网代码,坑了鱼鹰很多次(不知道最新版是否已经修复了这些bug),这里分享一篇网上的文章,因为鱼鹰也遇到过,靠它解决了其中一个编译优化问题,在此感谢作者。不过hal
    的头像 发表于 08-12 17:37 1263次阅读

    个人机智云开发实践:经验总结与技术分享

    在个人的机智云开发过程中,主要包括以下几个步骤1.项目创建与数据点设置2.在机智云平台上创建项目并定义所需的数据点,这些数据点将用于设备和云端的通信。3.无线通信模块固件烧录4.下载并烧录适用于所选无线模块的GAgent固件。例如,我使用了正点原子的esp8266模块,选择了对应的GAgentforESP8266固件。5.MCU方案代码移植6.将机智云提供的
    的头像 发表于 07-05 08:10 361次阅读
    个人机智云开发实践:<b class='flag-5'>经验总结</b>与技术分享

    瑞萨双通道同步升压控制器ISL81805调试经验分享及总结

    本文介绍了简要介绍了瑞萨 ISL81805 的特性性能等,并通过电源调试,为大家分享了相关的经验和注意点。
    的头像 发表于 06-17 18:54 1795次阅读
    瑞萨双通道同步升压控制器ISL81805<b class='flag-5'>调试</b><b class='flag-5'>经验</b>分享及<b class='flag-5'>总结</b>

    凯迪正大对电缆安全检查知识经验总结分享

    电缆作为电力传输的重要载体,其安全稳定运行直接关系到整个电力系统的可靠性。因此,电缆的安全检查至关重要。下面给大家分享一下武汉凯迪正大电气多年电缆故障查找总结经验,我们将围绕电缆安全检查的关键点,给大家分享。
    的头像 发表于 05-27 11:33 416次阅读
    凯迪正大对电缆安全检查知识<b class='flag-5'>经验总结</b>分享

    RZ/G2L Demo调试经验流程分享(1)

    r01us0553ej0107-rz-g(Release Note).pdf,r01us0556ej0102-rz-g(Board_StartUp_Guide_smarcEVK).pdf,对SMARC EVK of RZ/G2L的调试经验
    的头像 发表于 05-06 14:25 697次阅读
    RZ/G2L Demo<b class='flag-5'>调试</b><b class='flag-5'>经验</b>流程分享(1)

    BUG收集】为昕原理图设计EDA软件(Jupiter)免费评测活动常见问题及BUG收集

    感谢各位参与评测活动的工程师,请先认真阅读评测规则和本帖顶部的视频讲解。 如遇到bug可以在本帖反馈,会由为昕EDA的工程师们为各位解答。 【软件及使用指南】 软件使用指南见本帖底部视频 软件本体请
    发表于 04-25 18:23

    基于FPGA进行DNN设计的经验总结

    DNN中应用最广泛的是CNN和RNN,CNN是一种卷积网络,在图片识别分类中用的较多,RNN可以处理时间序列的信息,比如视频识别和语音识别。
    发表于 04-07 10:23 596次阅读
    基于FPGA进行DNN设计的<b class='flag-5'>经验总结</b>

    PLC系统的安装与调试流程

    PLC控制系统的安装与调试,涉及到各项工作,并且只能按序进行,一环紧扣一环,稍有不慎都将导致调试失败,不但延误工期,甚至会损坏设备。本文介绍了在现场实践中总结出的PLC控制系统的安装与调试
    的头像 发表于 03-27 17:08 793次阅读
    PLC系统的安装与<b class='flag-5'>调试</b>流程

    MCU不复位调试的小技巧

    场景,也并非无路可循。原则上只要我们通过仿真器调试时,做到代码不被重新下载覆盖,MCU 不被复位,就可能保留当前程序运行的状态,让 Bug 无处藏身。 02 实现方法 首先,我们将编译完成的工程烧录到 MCU,保证 MCU 中所运行的代码与要仿
    发表于 02-26 11:30 1274次阅读
    MCU不复位<b class='flag-5'>调试</b>的小技巧