當前位置: 華文星空 > 知識

有哪些讓你目瞪口呆的 Bug ?

2020-03-11知識

這是一個歷時5年,經過無數次排查才最終解決的BUG,而BUG的原因,卻又簡單到不可思議。

事情要追溯到2012年,我剛剛做程式猿不到1年,在公司做了一個網站程式,環境是小軟體公司常見的Windows+C#+SQLServer微軟組合,程式實作了什麽功能不重要,某天突然有客戶反映「登入不上去,一直提示驗證碼錯誤。」這個驗證碼我做的是隨機取兩個0-9的數拼個算式,之後生成圖片讓使用者填答案(例如圖片生成內容是1+1=?,客戶要填2)。答案存在session裏,使用者送出的時候就把填寫內容跟session裏面的答案比對。在確定客戶不可能一直做錯這種最初級算術題的前提下,開始了DEBUG。

然而我沒有想到的是,這個看似很小的BUG,卻如影隨形地跟隨了我5年。

1、初次交鋒

最初我在測試環境和正式環境下根據客戶敘述分別試驗,都未發現類似的BUG。嘗試遠端操作客戶電腦,問題重現,排除了客戶操作問題。嘗試重新獲取驗證碼、強制重新整理、清除緩存等方法無效後。受到水平高超的網咖網管的最強解決方案(重新開機、換機器)啟發,使用了【秘技:換個瀏覽器】,問題解決。

之後斷斷續續也有其他客戶反映同樣問題,也都透過此秘技恢復正常使用。但是這個奇怪的BUG原理卻完全不明白。使用同樣的功能,只有一部份使用者會產生這個問題,其他大部份人都是正常的。

2、獠牙初現

好景不長,換瀏覽器大法使用後沒多久,出現了第一批疑難雜癥患者:問題又在新的瀏覽器上重現。

再繼續換瀏覽器終究不是辦法,透過各種手段也沒排查到問題原因,甚至連公司的一個測試人員也遇到了這個BUG。之前更換其他內核瀏覽器就好用可能是因為緩存問題,但之前刪除過緩存並沒有起效。我們抱著玄學的態度,清除了瀏覽器緩存,然後重新整理頁面重新登入——登入成功。

原來IE這個功能其實清不幹凈。

於是我們的解決方案變成了【換成Chrome瀏覽器,如果還不行,就清緩存】

3、反擊

透過各種排查,最終確定BUG來源於session遺失,因為.net的session機制是本地cookies儲存了一個「ASP.NET_SessionId」,值與伺服器上的sessionid對應,從而確定會話是來自哪台電腦。我當時猜測是因為本地cookies中的sessionid與伺服器不對應,導致無法獲取會話資訊,所以session永遠是空的。而清除了cookies之後,重新為客戶端生成了新的sessionid,新的id有了對應後,問題解決。

因為在本地偵錯的用VS內建的IIS Express不會出現這個問題,所以我認為這是伺服器上IIS的BUG,但是網上檢索相關內容,無論是IIS的這個BUG,還是獲取不到session都沒有相關結果。

於是我心一橫,決定自己寫一套session,利用與iis類似的機制,透過客戶端cookies中的一個id來與伺服端對應,這樣直接幹掉了IIS的session,就可以不用為這個BUG煩惱了。

編寫過程很順利,新的session透過測試,正式使用。上線後經過幾次細節修改,基本完美執行。

與session遺失BUG的戰鬥也告一段落————本該是這樣的。

4、陰魂不散

樹欲靜而風不止,執行一段時間後,本應完全解決的BUG又卷土重來。與曾經一模一樣的情況,所有需要用到session的地方,都是返回空值。與曾經一模一樣的隨機使用者產生、難以復現。

反復排查,卻一無所獲,這個BUG最大的難點在於我們內部很難復現這個問題,所以十分難以偵錯,而出現了問題的客戶,一般都沒法連線到對方電腦操作。只能透過不斷地猜測原因,然後修改程式碼,祈禱這次的改動是有效的,這次的猜測是正確的。

經過了數次修改,效果卻並不理想。

5、柳暗花明

2017年的某天,正常工作中,在瀏覽器控制台中發現了一條異樣的cookie資訊

UserName=xxxx&Password=xxxx&copyright=xxxx

這條資訊是我設定的自動登入,只要選擇自動登入,便將帳號和加密後的密碼儲存到cookies中:

HttpCookie cookie = new HttpCookie ( "AutoLogin" ); cookie . Expires = DateTime . Now . AddDays ( 14 ); cookie . Values . Add ( "UserName" , ul . UserName ); cookie . Values . Add ( "Password" , ul . Password ); cookie . Values . Add ( "copyright" , "公司名" ); Response . Cookies . Add ( cookie );

在控制台裏面,copyright是亂碼的,因為公司名字是中文,因為沒報錯所以就沒關註過。進一步排查,終於發現了5年前那個BUG的產生原理:

cookies是以文本形式儲存在硬碟裏,而公司名字亂碼恰巧吞掉了字串結束的限定符,從而使得這個字串無限延伸,吞掉了後面的cookies。從而在framework獲取ASP.NET_SessionId的時候,取不到值,就產生了這個session黑洞。

至於為什麽部份使用者有這個問題,部份使用者沒有這個問題……因為大部份使用者ASP.NET_SessionId這條是在AutoLogin前面,不會被吞掉,而在後面的,都被吞掉了。

最後刪掉各計畫中在cookies追加版權資訊的程式碼後,問題解決,從此再也沒出現過session黑洞。

最終,一個困擾了我5年的BUG,竟然是這種令人哭笑不得的原因,而耗費了不少心血編寫和修改的自訂session元件,也因為經過幾年的時間,在各個計畫中已經有了非常廣泛的套用,修改成本較高。再加上一直正常使用也沒出什麽問題,就繼續用了下去。