程序员量子力学-海森堡式BUG

今天在阅读《The Pragmatic Programmer》的时候发现书中提到了Heisenbug让我想起来了多年之前在开发中碰到的一个海森堡式的BUG。
The Pragmatic Programmer数据库

海森堡是德国著名的物理学家,量子力学的创始人之一,“哥本哈根学派”的表明人物。单元测试

若是你们对这段历史或者物理原理不清楚的话,推荐你们阅读《上帝掷骰子吗》,很是好看的一本关于量子力学历史的科普书。测试

上帝掷骰子吗

海森堡对量子力学的一个重要贡献是提出了著名的“不肯定性原理”(又称“海森堡测不许原理”),在一个量子力学系统中,一个运动粒子的位置和它的动量不可被同时肯定。这是由于要观察就必须用光击中被观察的粒子,经过反射的光波来肯定粒子的位置。然而观测所发出的光必然会影响被观测的粒子。ui

海森堡式的BUG是该物理原理在软件开发中的一个表现,固然这是一个类比,它和量子力学没有半毛钱的关系。举个例子吧,当程序出现了一个bug,程序猿为了找到bug出现的缘由,在出现bug的代码处加入了一条打印语句,想要了解在出现bug的时候本地变量和参数的值以便肯定bug出现的缘由。然而奇迹出现了,当加入打印语句后,bug消失了。哦,买糕的,这条打印语句不就是射向粒子的那束光么?debug

下面,我来给你们分享一下我遇到的那个Heisenbug。设计

当时咱们团队作一个商用软件从Windows平台到Linux平台的移植,由于该软件早期是以Mac为平台编写的(那是Mac尚未像如今这样风靡),因此咱们的移植平没有遇到太大的困难,主要的工做是包括:调试

  • 用QT来实现全部的UI组件日志

  • 支持Linux下的数据库链接code

  • 移植C++非标准的使用orm

  • Unicode的支持

项目的前期很是顺利,然而就是当项目接近尾声的时候,一个可怕的海森堡式bug出现了,产品的release版本会出现一些随机的错误,这些错误都很奇怪,并无一个统一的表现。而这些错误在debug版本中彻底不会出现。为了解决这个问题,在boss的率领下咱们开始加班除虫。在当时公司加班仍是不多见的,一方面欧洲公司以人为本,并不鼓励加班;另外一方面咱们团队,你们能力都很强,不须要加班来解决问题。然而这个bug属于必需要解决的问题,加班在所不免。

但是要解决问题这个问题还真是不容易,由于问题不会出如今debug版本中,因此用gdb加断点单步调试的方式根本没有用。因此调试的方式就只剩下了打日志。通过我一天不断的加入日志,运行测试,加入日志,运行测试…… 最终终于找到了问题的缘由。通常状况下,找到问题的缘由比解决问题要困难的多,当你发现问题的缘由后,解决的方法就像秃子头上的虱子。

原来,这个问题是因为咱们生成软件版本的方法所形成的。

为了在build的时候自动的生成软件的版本,咱们的天才工程师想了一个好主意,那就是把版本信息写入Linux的可执行文件中(你们能够参考ELF的规范)。咱们的软件能够从文件中读出这个版本,让后经过API告诉任何组件或者使用者当前的软件版本是什么。不得不认可这是一个很是有创意的好主意,可是这也是引发错误的主要缘由。因为疏忽,在写入版本信息的时候,并无严格按照规范来写,因此其实版本信息超出了本应写入的位置,也就是说写越界了,破坏了程序数据,因此形成了release版本中的错误。但是为何debug版本没有问题呢?缘由大概是debug版本因为加入了大量的代码和调试信息,版本信息极可能只是覆盖了调试信息而没有影响程序的正常运行。

这么多年过去了,不少细节我已经记不清楚啦,然而对于这个海森堡式的bug,如今想一想,咱们应该能够作的更好:

  • 设计评审
    咱们鼓励创新,当引入一个新的解决方案,尤为是别人不多或根本没有使用过得方案时,咱们必须很是当心。由于没有人碰到一样的问题。认真的设计评审或许能够有所帮助。

  • 代码审查
    若是当时咱们可以认真的进行代码审查,也许咱们能发现这个问题。但也许即便进行代码审查,也不必定能发现这个错误。团队中没有几我的可以搞懂ELF的规范

  • 单元测试
    单元测试能帮助发现这个问题么?也许能够,当时咱们并无就这个功能引入任何的单元测试。

最后引用一个我发现的软件开发中的测不许原理:软件的需求和完成时间不可能同时测准,若是你清楚需求是什么,那么你就不知道何时能完成;若是你知道何时要作完,那你根本就不知道需求是什么。

相关文章
相关标签/搜索