程序员量子力学-海森堡式BUG
今天在阅读《The Pragmatic Programmer》的时候发现书中提到了Heisenbug让我想起来了多年以前在开发中碰到的一个海森堡式的BUG。
海森堡是德国著名的物理学家,量子力学的创始人之一,“哥本哈根学派”的代表人物。
如果大家对这段历史或者物理原理不清楚的话,推荐大家阅读《上帝掷骰子吗》,非常好看的一本关于量子力学历史的科普书。
海森堡对量子力学的一个重要贡献是提出了著名的“不确定性原理”(又称“海森堡测不准原理”),在一个量子力学系统中,一个运动粒子的位置和它的动量不可被同时确定。这是因为要观察就必须用光击中被观察的粒子,通过反射的光波来确定粒子的位置。然而观测所发出的光必然会影响被观测的粒子。
海森堡式的BUG是该物理原理在软件开发中的一个表现,当然这是一个类比,它和量子力学没有半毛钱的关系。举个例子吧,当程序出现了一个bug,程序猿为了找到bug出现的原因,在出现bug的代码处加入了一条打印语句,想要了解在出现bug的时候本地变量和参数的值以便确定bug出现的原因。然而奇迹出现了,当加入打印语句后,bug消失了。哦,买糕的,这条打印语句不就是射向粒子的那束光么?
下面,我来给大家分享一下我遇到的那个Heisenbug。
当时我们团队做一个商用软件从Windows平台到Linux平台的移植,因为该软件早期是以Mac为平台编写的(那是Mac还没有像现在这样风靡),所以我们的移植平没有遇到太大的困难,主要的工作是包括:
- 用QT来实现所有的UI组件
- 支持Linux下的数据库连接
- 移植C++非标准的使用
- Unicode的支持
项目的前期非常顺利,然而就是当项目接近尾声的时候,一个可怕的海森堡式bug出现了,产品的release版本会出现一些随机的错误,这些错误都很奇怪,并没有一个统一的表现。而这些错误在debug版本中完全不会出现。为了解决这个问题,在boss的率领下我们开始加班除虫。在当时公司加班还是很少见的,一方面欧洲公司以人为本,并不鼓励加班;另一方面我们团队,大家能力都很强,不需要加班来解决问题。然而这个bug属于必须要解决的问题,加班在所难免。
可是要解决问题这个问题还真是不容易,因为问题不会出现在debug版本中,所以用gdb加断点单步调试的方式根本没有用。所以调试的方式就只剩下了打日志。经过我一天不断的加入日志,运行测试,加入日志,运行测试…… 最终终于找到了问题的原因。一般情况下,找到问题的原因比解决问题要困难的多,当你发现问题的原因后,解决的方法就像秃子头上的虱子。
原来,这个问题是由于我们生成软件版本的方法所造成的。
为了在build的时候自动的生成软件的版本,我们的天才工程师想了一个好主意,那就是把版本信息写入Linux的可执行文件中(大家可以参考ELF的规范)。我们的软件可以从文件中读出这个版本,让后通过API告诉任何组件或者使用者当前的软件版本是什么。不得不承认这是一个非常有创意的好主意,但是这也是引起错误的主要原因。由于疏忽,在写入版本信息的时候,并没有严格按照规范来写,所以其实版本信息超出了本应写入的位置,也就是说写越界了,破坏了程序数据,所以造成了release版本中的错误。可是为什么debug版本没有问题呢?原因大概是debug版本由于加入了大量的代码和调试信息,版本信息很可能只是覆盖了调试信息而没有影响程序的正常运行。
这么多年过去了,很多细节我已经记不清楚啦,然而对于这个海森堡式的bug,现在想想,我们应该可以做的更好:
-
设计评审
我们鼓励创新,当引入一个新的解决方案,尤其是别人很少或根本没有使用过得方案时,我们必须非常小心。因为没有人碰到同样的问题。认真的设计评审或许可以有所帮助。 -
代码审查
如果当时我们能够认真的进行代码审查,也许我们能发现这个问题。但也许即使进行代码审查,也不一定能发现这个错误。团队中没有几个人能够搞懂ELF的规范 -
单元测试
单元测试能帮助发现这个问题么?也许可以,当时我们并没有就这个功能引入任何的单元测试。
最后引用一个我发现的软件开发中的测不准原理:软件的需求和完成时间不可能同时测准,如果你清楚需求是什么,那么你就不知道什么时候能完成;如果你知道什么时候要做完,那你根本就不知道需求是什么。
2014年4月03日 01:59
还有之前遇到的一种情况是有异步调用的时候,一debug,运行的顺序就不对了,于是一切正常,但是直接运行就是出错~
2014年4月03日 14:24
@小鬼: 多线程并发也有这个问题。
2023年1月24日 23:54
It is clear that the scientific world has yet to figure out the mysteries of quantum mechanics, as evidenced by the Heisenberg BUG. This glitch highlights the complexity of the real properties Stevenville underlying programming involved in this field, and how much more research and development is needed. Despite the challenges, it is encouraging to see the progress being made in this area, and it is only a matter of time before a solution is found.