这是Quora上的一个问题,米克的回答获得了13.5k的“赞”。他回忆说:曾经有个心理学博士找我查一个BUG,程序是他的一个学生写的。经常出现奇怪的输出。该程序所做的是从文件中读取数据,提出50个问题,进行一系列计算,然后根据博士的研究得出一个分数。该程序在大学的3B2上运行。他向我展示了程序并确认该错误是可重现的——每次我在问题之间切换时,总会闪烁一些奇怪的字符。我想这应该很容易,所以我答应了,我们同意按小时付款。Day1,来到这个3B2,用学生账号登录,找到用C写的源码,开始测试。代码的可读性很差,所有的代码都写在一行上,变量名都是三个字母,而且是随意组合的!我很高兴我选择了按小时收费。我已将代码格式化为惯用的样式,因此它具有一定的可读性。这样做之后,我使用curses库移动到屏幕上的一个点,打印问题和答案,然后等待响应。但是打印出第一行后,出现了一些乱码,大约1/2秒后,乱码被题目覆盖了。这个问题应该很容易解决,需要打印信息的地方只有五个,而且都是一闪而过的乱码。小东西,只需删除mvpwintw()就可以了。我删了之后开始编译,感觉问题解决的差不多了。但是运行的时候,干扰信息又出现了!只是乱码变了,但症状还是一样!我查看了代码,发现又回到了我改之前的样子!15个文件,混乱的格式,三个字母变量。为什么一开始不备份代码,我真想拍自己。我再次格式化它们,这次将代码放入三个不同名称的文件中。然后备份整个文件夹并设置权限为只读。编译后,一切正常。运行后,这个文件夹里又出现了15个文件!源码我改了之后没有删除,然后又出现了杂音信息。我想通了,肯定是硬盘某处的代码,编译的时候会把程序添加到我修改的代码中。所以我要搜索include区(/usr/include),因为我们用的是research版,所以机器上除了kernel以外的代码都在。头文件太多了,在3B2上搜索需要一些时间。以上是第一天的工作。Day2没有从磁盘搜索中得到任何结果,这意味着乱码要么被加密,要么在库中的某个地方。可是怎么也找不到,我决定把所有的文本文件都搜一遍,这次比昨天用的时间还长,第二天就这样过去了。Day3没有结果。字符串已加密。我不得不根据所有的头文件一点一点地检查它。这花费了相当长的时间,我们还警告学校有人可能获得了Phelps博士计算机的root访问权限。不过他们并不在意,说不定这只是一台实验室电脑而已。我打开了#include文件,没有发现任何代码。后来发现,这些被编译成一个文件。没关系,毕竟我们有源码,大不了要重新编译所有的库。Days4-6接下来的部分是最难的部分,我们终于把问题解释到学校课本上了。然后让Mark(我觉得他可以当Unix管理员,因为他娶了Dean的女儿)学习编译。***他终于同意让我做,因为他什么也做不了。第六天,编译工作终于完成了。我把修改后的代码拿出来,重新开始编译。一切正常,然后我运行它,伙计!问题又来了。源代码被拆分成15个文件,噪音又出来了。简直是变魔术了,感觉自己被打脸了,问题肯定不在源码上。菲尔普斯医生也有些不高兴。他觉得时隔这么久,也该写一篇新的了。“当然,”我失望地说,“你说得对,也许重写更好。”“好吧,我们明天开始重写,”医生说。Day7见鬼去吧,我不认输!我对菲尔普斯博士说:“你不用再给我钱了,给我时间,我一定会找到这个bug的。”Days8-14我学聪明了,他一定修改了一些库,我开始研究编译好的汇编(虽然之前完全不懂汇编),从开始学习到最终理解汇编花了六天时间代码。虽然没有发现任何异常,但这完全是浪费时间。Day15突然,我意识到问题可能出在编译器上,一定是。每次编译代码时,编译器都会在源代码中添加噪音。我以前也听说过这种情况。啊耶!我找到了!我们还有编译器的源代码,我查了一下,幸好找到了。编译链接器中的代码是这样的:1)检测所有对fopen()的调用,在打开的文件中寻找Dr.Phelps'problem,如果找到2)编译时,重写15个文件3)使用这15个文件编译博士程序,链接时会以-o的形式输出名称。该学生修改了编译器,将代码添加到Phelps博士的程序中。几天后,AT&T技术支持提供了原始的编译器和链接器代码,我们重新编译以替换修改后的编译器和链接器。但是,问题还没有解决。编译器被我们没有的其他源代码污染了。这些代码存在于当前的可执行编译器中,在编译编译器时会添加污染代码。但它并没有修改/usr/src中的代码,而是将其复制到一个隐藏文件夹中,修改编译器源码,编译,最后删除隐藏文件夹。AT&T花了很长时间才发现这个问题。学生修改了编译器以在编译器重新编译时添加污染代码。***我们不得不从另一台3B2机器上复制编译器的字节码文件版本,最终解决了这个问题。通过编译器的代码,我们还发现如果编译/sbin/login,会加入一些后门代码,允许任何人使用特定的密码登录root。可以通过调制解调器或Tymnet访问此计算机。最后,这件事引起了学校的注意。这人真是天才,也太可怕了吧!也有网友回答,该bug只存在于产品中,开发版中不存在或无法重现。这个人已经离开了。发生错误的地方是一个99.9%可靠的库。这是一个你永远不会怀疑的地方。这些年来,很多人都尝试过修复bug,但没有人成功地解决了逻辑错误的bug。只有运行一段时间后才会触发debug,需要领域知识,不了解的debugdeadline非常紧迫。堆栈溢出挂断。在StackOverflow上搜索问题,发现一年前就有人问过同样的问题,但是没有人回答。分号键坏了。看着我一年前的代码,我感觉就像“我写了这该死的东西”。该库没有文档。客户改变了他们的要求。在错误的目录下,rm-rf"Mycodeworks,Idon'tknowwhy"(这句话不用翻译)Meeting,meeting,meeting...作为一个程序员,让我去死吧。那么,你的噩梦又是什么呢?
