一行代碼引發(fā)慘案,這似乎有點(diǎn)兒夸張,但看完文章后你可能就會(huì)改變看法。
災(zāi)難降臨
時(shí)間回到1991年2月25號(hào),在一個(gè)月黑風(fēng)高的夜晚,一枚飛毛腿導(dǎo)彈,悄無(wú)聲息地飛臨沙特的達(dá)蘭美軍軍營(yíng)上空,而已經(jīng)連續(xù)作戰(zhàn)4天的美軍愛國(guó)者導(dǎo)彈防御系統(tǒng),沒能識(shí)別出這一危險(xiǎn)的目標(biāo)。這個(gè)大殺器直撲美軍營(yíng)地,造成了28名士兵死亡,100多人受傷,可謂慘烈!要知道整個(gè)海灣戰(zhàn)爭(zhēng)美軍一共才戰(zhàn)死了148人啊。
墨菲定律
在戰(zhàn)爭(zhēng)中大放異彩,被吹噓的神乎其神的愛國(guó)者防御系統(tǒng),是如何犯下這個(gè)致命的錯(cuò)誤的呢?這個(gè)起因倒是不復(fù)雜,其實(shí)在2月11號(hào),以色列軍方就已經(jīng)發(fā)現(xiàn),系統(tǒng)存在隱患。他們發(fā)現(xiàn)在愛國(guó)者系統(tǒng)連續(xù)工作8小時(shí)后,目標(biāo)捕獲精度會(huì)下降20%,在連續(xù)工作20小時(shí)以后,系統(tǒng)看起來(lái)似乎失效了。
在接到這一上報(bào)后,美國(guó)軍方大意了,他們覺得反導(dǎo)系統(tǒng)不會(huì)連續(xù)工作這么長(zhǎng)時(shí)間,雖然開始給軟件打補(bǔ)丁,但由于是在戰(zhàn)時(shí)狀態(tài),進(jìn)度比較慢,于是軍方發(fā)出命令,讓系統(tǒng)不要工作太長(zhǎng)時(shí)間。但是這個(gè)太長(zhǎng)時(shí)間是多久?并沒有說(shuō)個(gè)明白。于是墨菲定律又起作用了:如果事情有變壞的可能,不管這種可能性有多小,它總會(huì)發(fā)生。于是就發(fā)生了文章開頭的一幕。那么問(wèn)題出在哪兒了呢?
水落石出
隨后的調(diào)查顯示,問(wèn)題的根源,在軟件中一個(gè)隱藏很深的Bug。愛國(guó)者系統(tǒng)軟件,使用了一個(gè)3字節(jié),也就是24bit的變量存儲(chǔ)一個(gè)0.1秒的單位時(shí)間,存儲(chǔ)時(shí)間值和真實(shí)時(shí)間之間,有一個(gè)微小的差值,這個(gè)時(shí)間差值在系統(tǒng)運(yùn)行時(shí)逐漸累積,在系統(tǒng)不間斷長(zhǎng)時(shí)間運(yùn)行后,積累的時(shí)間差值過(guò)大,最終導(dǎo)致了嚴(yán)重問(wèn)題。
原來(lái)不像我們平常計(jì)算使用10進(jìn)制,計(jì)算機(jī)系統(tǒng)用2進(jìn)制存儲(chǔ)數(shù)據(jù),0.1秒變成2進(jìn)制是0.0001100110011001100110011001100....,這是一個(gè)無(wú)限循環(huán)小數(shù),當(dāng)用24bit 的變量存儲(chǔ)它時(shí),精度只保留到前24bit,后面的都被舍棄掉了,那這個(gè)誤差有多少呢?換算成10進(jìn)制是0.000000095秒,這看起來(lái)是一個(gè)很微不足道的誤差,但是工作100小時(shí)后,這個(gè)誤差會(huì)積累到0.000000095×100(小時(shí))×60(分鐘)×60(秒)×10(次/秒)=0.34秒。這似乎仍然是一個(gè)非常非常短的時(shí)間,然而,這足以讓以1676米/秒高速飛行的飛毛腿導(dǎo)彈,飛過(guò)569.84米,輕松突破本以為堅(jiān)不可摧的防線了。
給我們的警示
我們?cè)诰帉懘a時(shí),一定要注意每一個(gè)變量的位數(shù),而且需要注意的是,在不同的操作系統(tǒng),或者使用不同的編譯器時(shí),同一個(gè)類型的變量長(zhǎng)度可能都是不同的。這在移植代碼時(shí)尤其要注意,原來(lái)工作正常的代碼,換個(gè)平臺(tái),換個(gè)編譯器可能就不同了。
需要注意計(jì)算過(guò)程有沒有造成結(jié)果精度的下降,有沒有產(chǎn)生累積誤差。計(jì)算過(guò)程有沒有可能造成結(jié)果溢出,即結(jié)果小于0,或大于變量所允許最大值的可能。
整型,無(wú)符號(hào)型,浮點(diǎn)型等變量類型,不要混用,否則強(qiáng)制類型轉(zhuǎn)換可能導(dǎo)致不可預(yù)知的結(jié)果。
掃碼加入嵌入式交流群: