(点击上方公众号,可快速关注)
【伯乐在线导读】:本文综合整理自知乎问答帖《你在程序开发过程中有没有遇到无法解释的灵异现象?》和 伯乐在线 的旧文。知乎题主的补充:
大部分都是人祸。但是有没有至今还找不到原因,无法理解,完全超出认知。理论上不可能发生的事例呢?
下面是 mu mu 的分享,(伯乐在线已征得许可)
有天写了一行长一点的code,ide提示语法有错,我看了看,不可能,一定是ide脑残了。编译,ide显示error,语法有错。
不可能呀,我一个字一个字的看,不可能出错,一定是ide脑残的太厉害了,重启ide,还是报错。
我换了一行,一模一样的敲了一遍,没报错。
顿时觉得世界不真实了,开始怀疑是不是在做梦,甚至有点朝matrix那个方向想了。深呼吸,喝口水,擦了擦屏幕上的灰尘… 咦,怎么擦不掉?
原来,不知为什么在那一行前面有个 ` ,我一直以为是灰尘,就没管它。
论讲卫生的重要性。
下面是 gyrovague 博主的分享,
《遇到一个诡异 Bug,每逢周三就崩溃》,由 伯乐在线 - @Erucy 翻译
拿点儿喝的坐好,是时候讲讲我最喜欢的 bug 的故事了。
那是我第一份 IT 相关的工作:在一个生产重要医疗设备的厂商担任软件开发的暑期实习生。那些设备主要是麻醉给药系统和病患监控设备,后者就是在卧床患者旁边放着的发出“哔哔”声的那种盒子,上面会以图形方式显示患者的脉搏、血压、呼吸等等。如果心电图变成一条直线的话还会立刻召唤护士。当时的办公室里全是 2 米高的装着笑气的罐子,还有长着超级大胡子的嵌入式系统大拿,整屋子的人都在给各种设备准备文档,为了让它们通过 FDA 的认证。时不时还有人小声提到 10 年前没能在测试中发现的一个 bug,它导致了一台麻醉机在手术过程中间重启了。不用说,对于像我这种十几岁的新手,所有的生产系统肯定是不会让我们碰的。
(伯乐在线补注:一氧化二氮(Nitrous Oxide),又称笑气,无色有甜味气体,是一种氧化剂,化学式N₂O,在一定条件下能支持燃烧(同氧气,因为笑气在高温下能分解成氮气和氧气),但在室温下稳定,有轻微麻醉作用,并能致人发笑。)
不过他们还是给我安排了一份让人羡慕的工作,去测试一个在 1997 年听起来还十分时髦的原型项目:一个用 C++ 编写的服务器,它会监听患者监控设备的串口,然后把一些需要关注的事件转存到 SQL Server 数据库中,之后通过 CORBA 把数据发送到 Java Applet,于是医生或者相关人员就能通过互联网看到这个患者的状态了,它既能看到实时的数据,也能浏览之间的数据记录。帅气!只是那个时候我对这些语言和系统都一无所知!
接下来的几个星期就像杀猪一样的折腾,主要时间都花在了读懂让人头疼的 Visibroker ORB 手册,还有超级普通的类型转换 bug,不过我终于让我的“辛普森”系统磕磕绊绊地跑起来了,它用“Homer”(注:辛普森一家里的老爸)来记录和提供数据,然后用“Bart”(注:辛普森一家里的熊孩子)来进行显示。这几个星期让我觉得 CORBA 复杂得让人想死、AWT 让人头疼欲裂(比如 GridBagLayouts,呕)、applet 慢得像只蜗牛,不过 Java 看起来倒还像是个挺不错的语言。不过还有个小麻烦:C++ 服务器时不时就会突然崩溃掉,然后我开始尝试去搞明白到底是为什么。
因为我监听的那台监控设备在另一间屋子里,所以我绝大部分的开发和测试都是通过手动的“演示”模式来完成的,比如在一个循环里模拟一次心脏停跳之类的,据我所知,我的服务器从来没在这个过程中宕机过。不过在我或者别人手动摆弄那些控制器的时候,它确实崩溃过,尤其是在实际机器上操作的时候,不过我想尽办法也没能找到一个方法能让它稳定重现,甭管怎么做都不行。我把所有事件日志都记录到磁盘上,想找到在崩溃之前到底发生了什么,不过我小心翼翼地按照事件序列精确地手动重复了每一次事件(比如:把过滤器设置为 X,把控制器旋钮向右拧三个刻度,点击按钮……),我在两间屋子里跑来跑去(因为我在摆弄患者监控设备的时候是看不见我电脑上的日志的),但始终都没能让崩溃重现。不管是什么“鬼事件”(对我就是这么叫它的),它肯定是在造成崩溃的同时还逃过了所有日志。是不是有什么串口 I/O 或者硬件问题中断了事件?难道是宇宙射线把我 PC 上的数据位给改变了?
我把整天整天的时间都用来尝试去重现这个错误,但是毫无结果,在经历了几个星期的挫折之后,我最后干脆在所有从串口收到事件和写入数据库的操作中间都加了 printf 语句,在这个过程中,我重新检查了每一行代码,然后终于逐渐见到了曙光。
当我创建数据库结构的时候,为了节省空间而犯了一个错误,一个新手常犯的错误:把时间戳当成主键了。所以如果两个事件在一个毫秒内发生的话,数据库就会抛出主键唯一性约束的异常(译注:SQL Server 的 datetime 类型的精度其实不是1毫秒,而是3.33毫秒)。我之前注意到这个问题了,不过我觉得这种情况非常罕见,而且只会在没那么重要的环境中发生(比如在鼓捣监控设备内部配置的时候),所以我只是加了个 catch 语句,在日志中写了一条警告信息,然后继续执行后面的操作。
但是!这是个老派的代码,记录日志使用 C 语言风格的代码编写的,把日志字符串记录到了一个长度为 80 个字符的缓冲区中。唯一性异常这个消息本身是个常量,而日志的时间戳是格式化的,也就是实用了完整的英文的星期拼写(%E),所以输出就类似于“Monday, July 17, 1997, 10:38:47.123”。最后就是因为英文里面星期几的拼写有个有意思的属性:
星期几 | 单词长度 |
---|---|
Sunday | 6 |
Monday | 6 |
Friday | 6 |
Tuesday | 7 |
Thursday | 8 |
Saturday | 8 |
Wednesday | 9 |
明白了吧?星期三(Wednesday),而且只在星期三的时候,如果有人在监控器配置那儿手动进行了一个特定操作的话,就会在同一毫秒内产生两个事件,于是导致数据库抛出异常,而这个异常的消息包括字符串结尾的终结符的话,则刚刚好 81 个字符,导致了 80 个字符的缓冲区溢出,把程序搞挂了!
在那之后,在所有需要使用的数据库表中,我都会确保去用一个专门的、自增的整数 ID 作为主键,然后用 ISO 格式(也就是 YYYY-MM-DD)而不是星期几来记录所有日志。这些年来,我学到了不管一个 bug 看上去多么随机和不可预测,如果你挖得足够深的话,总是能找到一个符合逻辑的解释,极少有真的“不相关”的错误,几乎都是你特么自己的错。
下面是 Devymex Wang 的回复分享,(伯乐在线已征得许可)
你们说的根本就不是灵异事件好吗?下面是真事!
某公司有个码农工作压力太大,天天晚上加班到半夜,最后受不了跳楼死了,他的机位从此就一直空着。但令大家都感到非常奇怪的是,有几次早上来上班时却发现这台机子竟然开着!大概是因为电源有问题吧,但这个项目经理是个疑神疑鬼的人,每次经过这里都绕着走。
到了新一届招人,一个女孩被分到这个项目组。项目经理让她坐这个空着的机位,谁也没敢告诉她之前的事,只是让她接手原来同事的工作。过了没几天,她写的代码被测出来一个bug,可她水平确实比较差,怎么都调不通。她又不敢问同事,只好向男友求助(她男友是另一家公司的大牛)。男友说现在很忙,晚上10点以后才有空。
那天她只好等到晚上10点,男友终于有空了。这时公司里只剩下她和项目经理两个人。她男友通过远程桌面帮她调试的时候,她要去个厕所便起身离开了坐位。过了一会项目经理下班回家,经过这里时用余光看到屏幕的上的代码好像在动!他定睛一看,屏幕上的代码正在一行一行的往下写,可是机位上并没有人!!!
第二天这个项目经理没来上班,而是给 HR 发了封邮件,提交了辞职申请。
觉得本文有意思?请转发分享给更多人
关注「程序员的那些事」,编程更有趣
友情链接