程序員最恐怖的噩夢是什么?
這是 Quora 上的一個問題,其中 Mick 的回答獲得了 13.5k 的“贊同”,他是這么回憶的:
曾經(jīng)有位心理學(xué)的博士雇我查一個 BUG,程序是他的一個學(xué)生寫的,經(jīng)常會出現(xiàn)奇怪的輸出。程序的功能是,從文件中讀取數(shù)據(jù),提出 50 個問題,進(jìn)行一系列計算,然后基于這位博士的研究來得出一個分?jǐn)?shù)。程序跑在大學(xué)的一臺 3B2 上。他給我演示了程序,確認(rèn)這個 Bug 可以重現(xiàn)——每次在問題之間切換的時候,總會閃出一些奇怪的字符。我覺得這應(yīng)該很簡單,所以答應(yīng)了他,并且我們同意按小時付費(fèi)。
Day1
我來到這臺 3B2 面前,用那個學(xué)生的帳號登錄,找到了用C寫的源代碼,并開始測試。代碼可讀性非常差,所有的代碼都寫在了一行,變量名都是三個字母,而且還是隨機(jī)組合的!真慶幸我當(dāng)初選擇按小時收費(fèi)。我把代碼格式化為習(xí)慣的風(fēng)格,這樣看起來多少還能讀。
做完之后,我用 curses 庫移到屏幕上一個點,打印一個問題和答案,然后等待回應(yīng)。但是在打印出***行之后,出現(xiàn)了一些亂碼,過了大約1/2 秒之后,亂碼被問題覆蓋掉。這個問題應(yīng)該很容易解決,只有五個地方需要打印信息,所有的地方都出現(xiàn)了一閃而過的亂碼。小意思,只要刪掉 mvpwintw ()應(yīng)該就 ok 了。我刪掉之后開始編譯,覺得問題差不多解決了。但是運(yùn)行的時候,干擾信息又出現(xiàn)了!只是亂碼變了,但是癥狀還是一樣!
我檢查了一下代碼,發(fā)現(xiàn)竟然回到了我改之前的樣子!15 個文件,混亂的格式,三個字母的變量。當(dāng)初為什么不備份一下代碼呢,真想射自己一槍。我再一次格式化它們,這次把代碼放到三個文件中,以不同的名字命名。 然后備份了整個文件夾,并且將權(quán)限設(shè)置為只讀。編譯之后,一切正常。一運(yùn)行,這個文件夾中又出現(xiàn)了 15 個文件!我改過之后的源代碼沒有被刪除,然后干擾信息又回來了。
我明白了,這一定是在硬盤的某個地方的代碼,在編譯的時候會將程序添加到我修改的代碼中去。所以我準(zhǔn)備搜索一下 include 區(qū)域(/usr/include),因為我們用的是研究的版本,所以除了 kernel 別的代碼都在機(jī)器上。頭文件太多了,所以在 3B2 上搜索需要花一些時間。以上,就是***天的工作了。
Day2
從磁盤的搜索中沒有得到什么結(jié)果,這說明這些亂碼要么是被加密了,要么就是在 lib 中的某個地方。但是我沒有搜到,我決定搜索所有的文本文件,這次花的時間比昨天更長,第二天就這這樣過去了。
Day3
沒有結(jié)果。字符串是加密的。我只好根據(jù)所有的頭文件來一點一點查了。這會花費(fèi)相當(dāng)多的時間,我們同時還警告了學(xué)校,可能有人得到了 Phelps 博士計算機(jī)的 root 權(quán)限。但他們卻對此并不關(guān)心,可能只是一臺實驗室的計算機(jī)吧。
我打開#include 文件,卻沒有發(fā)現(xiàn)代碼。后來發(fā)現(xiàn)這些都被編譯成一個文件了。也沒什么關(guān)系,畢竟我們有源代碼,大不了就重新編譯所有的庫。
Days4-6
接下來是最難的部分了,我們好不容易向?qū)W校的書***說明了問題。然后讓 Mark(我覺得他能做 Unix 管理員完全是因為娶了 Dean 的女兒)開始學(xué)習(xí)編譯。***他終于同意交給我來做,因為他什么都不會。在第 6 天***,編譯工作終于完成了。
我拿出修改之后的代碼,重新開始編譯。一切正常,然后我運(yùn)行了一下,天吶!這問題又出現(xiàn)了。源代碼分成了 15 個文件,干擾信息又出來了。簡直跟魔法一樣,我覺得自己被打敗了,問題肯定不在源代碼里。Phelps 博士也有點不樂意了,他覺得這么長時間,即使重新寫一個也該完成了。“當(dāng)然”,我失落地說,“你是對的,說不定重寫比較好。”“好的,我們明天開始重 寫。”博士說。
Day7
見鬼去吧,我不會認(rèn)輸?shù)?!我?Phelps 博士說:“你不用付給我錢了,只要給我時間,我一定要找到這個 bug。”
Days8-14
我學(xué)聰明了,他一定是修改了一些庫,我開始研究編譯出來的匯編(雖然我之前根本就不懂匯編),從開始學(xué)習(xí),到***看懂匯編代碼,花了六天。雖然根本沒發(fā)現(xiàn)什么異常,完全就是在浪費(fèi)時間。
Day 15
突然,我意識到,問題可能出在編譯器上,一定是。每次編譯代碼的時候,編譯器就會往源代碼中添加干擾信息。我以前也聽說過這種情況。
啊耶!我找到了!我們也有編譯器的源代碼,我查了一下,謝天謝地,終于找到了。編譯器鏈接器中的代碼是這樣的:
1) 檢測所有對 fopen()的調(diào)用,在打開的文件中查找 Phelps 博士的問題,如果找到
2)編譯的時候,重寫 15 個文件
3)使用這 15 個文件編譯博士的程序,在鏈接的時候會輸出-o 形式的名字
編譯器被這個學(xué)生修改了,以便往 Phelps 博士的程序中添加代碼。
幾天之后,AT&T的技術(shù)支持提供了原版的編譯器和鏈接器代碼,我們重新編譯,替換了被修改的編譯器和鏈接器。
但是,問題還沒有解決。編譯器被其他我們沒有的源代碼污染了。這些代碼存在于現(xiàn)在可執(zhí)行的編譯器中,在編譯編譯器的時候,會加入污染代碼。但是它并 不修改/usr/src 中的代碼,而是將其復(fù)制到一個隱藏文件夾,修改編譯器源代碼,編譯,***刪除隱藏文件夾。AT&T發(fā)現(xiàn)這個問題花了好長時間。這個學(xué)生修改了編譯 器,讓編譯器重新編譯的時候加入污染代碼。***我們不得不從另一臺 3B2 機(jī)器上復(fù)制過來編譯器的字節(jié)碼文件版本,才終于解決這個問題。
通過編譯器的代碼我們還發(fā)現(xiàn),如果編譯/sbin/login 的話會加入一些后門代碼,可以允許任何人使用特定的密碼來登入 root。這臺電腦可以通過調(diào)制解調(diào)器或 Tymnet 接入。終于,這件事引起了校方注意。
這人真是個天才,不過,也太恐怖了!
其他網(wǎng)友回答
-
Bug 只在產(chǎn)品中有,開發(fā)版本中卻沒有或者不可重現(xiàn)
-
bug 觸發(fā)的幾率很小很小,卻又不能小到可以忽視
-
去改不是你寫的代碼中的 bug,原來寫代碼的這家伙已經(jīng)離職了
-
發(fā)生 bug 的地方是 99.9% 可靠的庫,是你絕對不會懷疑的地方
-
幾年來很多人嘗試去修改的 bug,但是沒有人成功過
-
存在邏輯錯誤的 bug,只有在運(yùn)行一段時間之后才會觸發(fā)
-
debug 需要特定領(lǐng)域的知識,正是你不懂的
-
debug 的 deadline 很緊
-
Stack Overflow 掛了
-
在 Stack Overflow 上搜索問題,發(fā)現(xiàn)有人一年前問了同樣的問題,但是沒有人回答。
-
分號鍵失靈
-
看自己一年以前的代碼,有種“這真他媽是我寫的”的感覺
-
庫沒有文檔
-
客戶又改需求了
-
==寫成了=
-
IE(如果你做前端)
-
Github merge 沖突
-
在錯誤的目錄下 rm -rf
-
“My code works, I don’t know why”(這句話不需要翻譯了)
-
開會,開會,開會……作為程序員讓我去死吧
那么,你的噩夢又是什么呢?