你最痛苦的一次找程序 bug 的經歷是?

總管上面的現有的答案,可以發現你們的bug有三種:第一種是語法的bug,這個吹吹水啦。第二種是數據的bug,這種bug是比較頭疼的,但是也不是不可以解決。第三種bug是第三方bug,但是……

同志們,見過Oracle JDK給你挖的坑嗎!

去年寫一些機器學習的模型上線去跑,要做IO把處理下輸入數據。非常happy的寫完了,然後就交給了上線實施人員。

過了一會兒,上線實施小哥表示:嘿,兄弟,你這輸出結果不對啊!

我一臉懵逼:不能啊,在我這都是正確的啊!是不是你傢伙手欠改了啥??

小哥:卧槽,我就改了下配置文件卧槽!

我:等著,我去現場。

小哥:(⊙_⊙)

我:╭(╯^╰)╮大步流星飛赴前線,來來來,我瞅兩眼。哎呀,這個配置

小哥:這個配置怎麼可能有問題!

我:……的確看不出來問題……開log看看??

小哥:這不是log么……你看!

我:為啥一點問題都沒有……為啥……為啥……難道是我模型有bug?

小哥:你的鍋反正╭(╯^╰)╮

我:T^T不對啊,我公式推導都過了,這個鍋寶寶不背!要背也是你背

小哥:我們還是討論下甩鍋問題吧……

我:這活兒就咱倆人做的摔給誰……除了java se的庫,多餘的一個庫都沒用……總不能甩鍋給……Oracle吧……

小哥:就Oracle吧

我:(⊙o⊙)…對哦,線上系統是1.6唉……我的系統是1.8啊……

小哥:你用了1.8的什麼特性?

我:天地良心,我照著1.6寫的!多餘的一點都沒用!

小哥:(⊙o⊙)…咱切成1.8試試……卧槽,正常了發生了啥!

我:麻蛋,log全開!全開!我要上diff直接看區別

小哥:麻蛋,全開全開!

當半小時後,log全開了以後……(⊙_⊙)我們將log全部展開,一行一行比對……終於發現在一個角落裡面,有一個字元串數組長度多了一位。而這個字元串數組是用split生成的……

我、小哥:wtf?

最後,在oracle jdk的bug list 裡面發現了這個bug的兩次報告,結論如下:

這個bug事實上是早期split的設計與描述略有不符,在1.8裡面修正了這個bug,但是呢,以前的jdk就那樣啦,我們就不改了啦~

於是oracle背鍋成功。

==

上面說了三種bug,是一般程序員會碰到的,下面說說第四種bug……多數程序員不會碰到

==

第四種bug是這樣的,如果你的程序裡面,有隨機數發生器,那麼你如何跟蹤和調試bug呢?

不幸的是,我們搞機器學習的,特別是搞貝葉斯派機器學習的,經常處理這種bug。

在我們的程序中有大量的計數器,這些計數器對應著模型中的某些參數。而我們的程序就像是一個在爬山的人,隨時會根據山的走勢與峻峭程度選擇路徑。而判斷峻峭程度的依據就是計數器。

這裡,計數器只有兩個限制:

1、計數器的數據必須大於等於0。如果小於0,那麼本來想往山頂爬的,最後就爬溝裡面了。

2、根據計數器的結果計算一系列概率,形成一個骰子,然後決定往哪個方向爬。

第一個非常簡單,而第二個非常蛋疼。蛋疼在於:當你第二條限制被打破的時候,一定說明,在前面的某個時間點,第一條限制被打破了。但是……麻蛋勞資第二條限制是一個概率分布的限制啊!!!換句話說,我根本就不可能知道在什麼時候什麼時間什麼地點第一條限制被打破了!

導師告訴我:你想要力量嗎?

我:(⊙o⊙)嗯!

導師:自己想,對著模型重新敲一邊代碼……

我:T^T嗯!

我們的模型裡面的公式不能給大家看,但是可以從側面告知大家公式的複雜度:

多數符號帶有上標和下標,而他們的上標和下標裡面,又有上下標……如是反覆。這樣,計數器的名字在java裡面怎麼明明呢?一般而言就是用簡化的LaTex代碼表述這個符號,然後寫進去。

然後,在第二步中,那個骰子的形成過程中,多數計數器都以不同方式纏繞在算式上上下下……

由於公式太長,往往將製造骰子的過程單獨放一個方法,投出骰子獲得結果單獨一個方法,根據骰子的結果改變計數器又是一個方法——大骰子投出去往往牽連多個小骰子……(⊙_⊙)反正隨隨便便5-600行代碼就出來了。

這種bug很難找,第一次找花了三天。後來有經驗了,也要一個小時左右去逐個變數循環輸出其值,然後在數值的大海里尋找bug的蛛絲馬跡。

這種bug比較新鮮,所以寫在這裡。

你最痛苦的一次找程序 bug 的經歷是



推薦閱讀:

學機械的起薪普遍較低,好多都轉行搞it和金融,怎麼看待這種現象,這種現象會對中國產生什麼影響?
開發中有沒有遇到過特別難以交流的測試人員?
關於編程,你得到的一個最好的建議是什麼?
如何自己創建一種編程語言?

TAG:程序員 | 編程 | 計算機 | 互聯網 | Bug |