21-2038年世界会毁灭吗?
1. 程序里藏着“小怪兽”?


你有没有写过作文写到一半发现少了一个“。”?或者答题卡不小心涂错了格子,最后整张卷子对不上号?这些“乌龙”听起来是不是有点小抓狂?
其实啊,在编程世界里,也常常会遇到这样的小状况,我们把它叫做——Bug。
“Bug”?你没听错,就是那个英语里表示“小虫子”的词。而要解决这些 Bug,就叫“Debug”,字面意思就是“消灭虫子”!
但你以为这是在开玩笑吗?错!这个词的背后,有一段非常奇妙的真实故事。
不过,这两个词在计算机领域意思就不一样了,bug 指的是程序里可能出错的地方。“debug”呢,就是排除这些问题。
那你可能会问了,计算机程序里的错误跟虫子有什么关系呢?
2. 那只“程序里的蛾子”
上世纪中叶,有位非常了不起的女性程序员,名叫格蕾丝·赫柏。她不仅是世界上第一批程序员之一,还是美国第一位女性海军将军,更厉害的是,她参与研发了人类最早的通用计算机之一——马克一号。
有一天,她正在测试“马克二号”的时候,计算机突然坏掉了。赫柏带着团队东找西找,最后居然在机器里发现了一只真的蛾子,卡在电路中间!她小心翼翼地把它取了出来,机器又恢复了正常运行。
她把那只蛾子贴进了当天的工作记录,还标注了一句话:我发现了一只虫子——也就是“我发现了一个 bug”。
现在,这一页工作记录被送进博物馆保存了起来。下面图片显示的,就是这一页记录,你还能看到当年的那个 bug 呢。

没想到,这一幕被载入史册,“Bug”从此成为“程序错误”的代名词,而赫柏也被大家戏称为“debug 之母”。
3. 一个 Bug,引发全球危机?

不过,有意思的是,“debug 之母”本人竟然是世界上最可怕的 bug 的制造者。这个 bug 有个名字,你可能听说过,叫做“千年虫”。
时间飞快地来到了20世纪末。
因为那个时候,计算机才刚刚诞生,运算能力非常弱,内存也非常宝贵。在给“马克一号”编程的时候,格蕾丝就使用了一个简化年份的方法。这个做法,咱们平时说话也会用到,比如把 2008年,简化成“零八年”,把 2021 年简化成“二一年”。
格蕾丝就设置,程序如果要记录“此刻”的时间,也就是正在发生的事情所处的时间,那么就把它的年份简化为后两位,然后呢,默认前面有一个“一九”的前缀。换言之,如果记录的年份是“六五年”,那就默认这是“一九六五年”,如果是“八六年”呢,就默认是“一九八六年”。
这个方法很好用。后来,其他的程序员在编程的时候,也沿用了这个方法。在很长的一段时间里,几乎所有的程序,都是这样来处理年份的。
这在当时没什么问题,大家默认前面都是“19”。可你想想,一旦过了1999年,下一年就是“00”(2000年),电脑一看:“咦?这不应该是1900年吗?”于是,系统就“穿越”回了一百年前。
因为这个 bug,也就是虫子,和 2000年这个年份有关,所以大家就叫它“千年虫问题”。
其实,早在1958年的时候,就有人意识到了“千年虫问题”,但很多人并不觉得这是个问题,毕竟谁都没想过自己写的程序能用几十年嘛。
但是,随着时间一天天靠近 2000年,人们渐渐发现不对劲了,到1998年、1999年的时候,竟然还有好多程序都在用这种表示时间的方法,其中还包括很多政府、银行、军队使用的程序。当时的人们都特别紧张。
你可能会觉得,这有什么好紧张的呢?发现时间不准了调一下不就完了吗?
其实不是的,在计算机里,时间对不上可是个很严重的错误。它有可能导致正在运行的程序突然崩溃。
这要是发生在我们自己家里的计算机上倒还好,最严重的后果,无非就是报废一台计算机。但在其他地方可就不一样了。比如军队吧,现代军队是特别依赖计算机的。战斗机保持飞机平衡、搜索和锁定敌人都要靠计算机帮助。坦克瞄准敌人开火,干扰敌人的导弹让它们打不准,靠的也是计算机。
你可以想象一下,假如一架战斗机在1999年的12月31日晚上出去执行任务。飞着飞着,时间一过0点,战斗机上的电脑突然就不工作了,战斗机一下子失去了控制,搞不好会载着武器一头就撞向了城市。这可太糟了吧。
如果哪个国家在这个倒霉的时候发射了一枚导弹,那可就更惨了,负责给导弹导航的计算机可能突然会失控,那谁都不知道导弹会打到哪里去。甚至还有人认为,核弹的控制系统也会受到影响,万一系统崩溃,核弹自己发射了,那可是灾难性的后果。
当然了,核弹自己乱发射这样的事可能不会发生,但“千年虫”确实会造成很可怕的后果。像政府的计算机里记录着大量的公民信息,银行的计算机里记录着每个人的账户上有多少钱。如果这些计算机出了问题,就会引起大混乱。
4. 最后一刻的人类总动员

1998年到1999年,人类历史上上演了一场罕见的“全球程序大检查”:
- 各国投入巨资检查程序;
- 程序员通宵达旦寻找隐藏的 Bug;
- 政府做宣传,提醒企业更新系统;
- 连录像带租赁店都得更新时间系统……
结果呢?虽然 2000年确实发生了一些“小插曲”(比如有人还录像带被罚了100年的滞纳金),但灾难并没有发生,人类成功挺过了这场数字风暴。
5. 那下一次危机会是啥时候?

别急,下一场“潜在危机”已经悄悄潜伏中。科学家们发现,2038年左右,某些基于旧系统的计算机会再一次面临“时间爆炸”,这一次不是“千年虫”,而是“二进制虫”。
不过别担心,这一次计算机科学家和程序员们吸取了前面的教训,已经在提前准备中。只要我们在软件上线前认真调试,就不会再被 Bug 吓得团团转啦!
你看,对计算机科学家和程序员来说,提前发现问题并提前作出处理是一项特别重要的技能。实际上,现在人们在编写程序的时候,都希望在程序投入使用之前就找到 bug,并把它们解决掉。
6. 编程思维训练场:极端情况测试法

那我们平时该怎么做,才能让程序更“抗打击”呢?
答案是:主动设想最糟糕的情况!(预想极端情况)
举个例子:我让你编写一个能做除法的程序,输入除数和被除数,就能算出它们的商。这听起来非常简单吧?如果你学过简单的编程,可能不到一分钟就能写出这个程序。那你能不能想想,这个程序有什么地方可能会出错呢?能不能给它 “debug” 一下呢?
你要如何思考呢?你要想想什么情况下除法不能被执行呢?——在除法里,0是不能做除数的。
所以,如果有人在除数这一栏输入了 0,那么程序就可能会出错。这就是一个极端情况,是要提前做好应对准备的。如何准备呢?加一个条件判断:如果有人在除数一栏输入了 0,那程序就不会进行运算,而是直接弹出一句提示:“0 不能作为除数”。
这个 debug 思路,是因为数学规则早就告诉我们,除数不能为 0。但程序不知道这个规则,除 0 操作就会让程序崩溃。我们程序员的任务就是要程序知道这个规则,规避错误。
那还能不能继续“debug”呢?当然可以了,我们还是思考极端情况,还有什么比输入 0 更糟糕的情况吗?
有人可能在输入框里填入一串“哈哈哈哈”甚至是“😊”表情符号。你是不是觉得离谱?可程序员就得像一个“超级挑剔”的测试员,专门去想这些稀奇古怪的问题,我们也得提前对这些情况做好准备。——这种方法我们就叫做极端情况测试法。
我当时更我学员说这个测试方法时,他(她)们就觉得:这明明是一个除法程序,怎么会有人输入文字、表情符号呢?这不是在搞破坏吗?
我给出的回答是:程序员在给程序挑错的时候,就像是故意给程序搞破坏。这样才能做到万无一失。
所以你要深刻明白一点:不是为了“搞破坏”,而是为了把一切可能出错的地方提前找出来。
7. 不只是编程,生活中也能用!

这种“为最坏做准备”的思维,不只在编程中有用。
- 比如考试时,准备两支笔防止一支突然坏掉;
- 数学考试时,为了预防老师不提供草稿纸,我们自己提前准备草稿子;
- 演讲比赛前,请同学扮“毒舌评委”练练胆、故意挑刺。虽然真正的评委可能不会这样苛刻,但提前考虑好最糟糕的情况,可以确保万无一失;
- 出门旅行时,备好充电宝、雨伞和备用路线……
这些其实我们都可以提前考虑到,提前做好准备。
而这些,就是生活中的“Debug”呀!不是等问题来了才手忙脚乱,而是提前打好“补丁”。
8. 总结

Bug 不一定是“小虫子”,但调试程序真的像是在“打怪兽”。
只要你有“发现问题、预想风险、提前应对”的意识,就能从一个普通的程序员,变成能扛得住风暴的“代码勇士”。
当然,再优秀的程序员也难免会犯错。所以,debug 永远是程序员工作中重要的一部分。不过对于生活中,debug 的思维也是非常有必要的。
更新日志
ff458
-于87164
-于6b1d4
-于a12f3
-于cca0e
-于05983
-于05632
-于c761c
-于1c35a
-于aed17
-于f14b0
-于e6ce4
-于69882
-于772c4
-于e6a0f
-于cbb3a
-于610fe
-于f08aa
-于76989
-于86c50
-于027da
-于