有人說,程式設計師寫**的能力一定要強,如果寫**不行,錯誤百出,那他除錯能力一定要強。總之,兩個優勢中至少要占有乙個,否則寫**又爛,自己又改正不了,豈不是糟糕至極。本人不才,寫**經常丟東拉西,每次檢查自己的程式,幾乎都能發現新的bug。在驚喜不斷的同時,也鍛鍊了我臨危不懼的神經。開始我很害怕發現程式的錯誤,寫好程式都不怎麼用,發現bug後也是盡快修復,很少去系統地檢查和測試。後來我發現這樣做其實效率很低,bug不會因為不檢查不執行就不存在,如果不主動去檢查和查詢原因,等待自己的會是無休無止的bug發現與修復的迴圈。而且發現bug之後,不應該急於修復,因為很多bug是隱藏極深的,通過現有的除錯手段很難直觀地定位。如果不小心改錯了,會使事情更糟。
如果我遇到乙個bug,我會盡量讓這個bug的出現變得規律、固定,並會嘗試新增、刪除或者調整一些**的順序,來實驗bug出現的情況。這樣除錯後,肯定有些情況,bug是不會出現的,而另一些情況,bug則會出現。這是乙個簡單的二分法,錯誤的原因將執行結果分為兩半,一邊是正確的,一邊是錯誤的。我的目標就是找到這條分割線。很多時候,分割線並非那麼直觀好找,這是就要靠程式設計師的直覺,或者說靠他的經驗以及對程式和執行環境的了解情況。多次的實驗往往會觸發人的靈感,有時會覺得是這裡的問題,有時又覺得是那裡的問題,裁判它們的方法很簡單,就是實際去驗證。有意思的事,問題癥結所在,往往在開始的很長時間內是意識不到的(如果能意識到該問題,那它能成為一種bug的概率就很小)。我把這個過程畫成了一張流程表:
我寫這篇文章也是因為我發現了乙個很有意思的bug。不是因為它有多難,而是因為它的原因讓我很意外。這是乙個嵌入式的任務,有一塊板卡,是用uboot(一種bootloader)啟動的,之後會載入板卡flash上儲存的作業系統linux 2.4。我的任務是將ucos移植上去。因為uboot的bootm命令基本上是專為linux的zimage設計的,我就用cp.b和go兩個命令組合,讓uboot來載入我存在flash上映像。而且在真實移植ucos之前,我需要先驗證幾個裝置的驅動,比如led燈、數碼管、串列埠、定時器之類的。問題就在我編寫裸機程式驗證數碼管時出現了。數碼管操作其實非常簡單,只需要在特定的位址寫資料即可。但就在我寫完數碼管後幾秒鐘,板卡就沒有了輸出(因為缺乏除錯手段,我能看到的現象就是板卡沒有了輸出,連怎麼異常的都不知道)。因為數碼管所在的這個位址離其它位址都非常遠,我以為是記憶體控制器或者mmu的問題。但因為時間關係,我對它們無法詳細了解。後來驗證的其它裝置的裸機程式都很正常,ucos也成功移植了。但即便是在ucos中,也仍然是無法對數碼管讀寫,讀寫後兩三秒內必然當機。
直到乙個多月後,我才再有時間來再次驗證這塊板卡上的程式。之前的除錯數碼管的裸機程式,早就多次的修改和除錯中無法回溯了,只記得可能是數碼管所在的記憶體控制器或mmu的問題。我這次詳細地閱讀了板卡控制器的文件,並分析了uboot對記憶體控制器和mmu的操作**,發現它們存在對這塊位址的對映,這裡查不出問題。使用uboot的mw指令訪問數碼管,也是正常的。然後我在ucos bsp的啟動**裡,新增了對數碼管的操作,並讓它死迴圈,發現它還是在兩三秒後掛掉。再去掉對數碼管的操作,讓它死迴圈,發現它竟然仍然掛掉。這時我才覺得,掛掉並非因為對數碼管的訪問,而是另有原因。奇怪的是,如果我不在開始處死迴圈,而是讓它盡快地開啟ucos的任務排程,就一切執行良好。我想不出這是什麼原因,好在我對uboot的異常處理機制**剛進行過分析,我修改了ucos bsp的異常接收**,讓它把所有的異常全都列印出來。然後繼續在開始處死迴圈,好吧,我發現在死迴圈時,有異常被響應,並導致當機。檢查uboot的go命令實現,原來其中並沒有關中斷,而ucos bsp啟動開始處,也沒有關中斷,恰好uboot中啟動了一些定時器的中斷,導致死迴圈中中斷也會到來。再檢查ucos的中斷響應和恢復**,發現中斷響應時會儲存任務上下文,退出時會恢復任務上下文,並支援任務搶占。等等,這時ucos的資料結構根本沒有初始化,而且也沒有開啟任務排程,這時中斷當然會紊亂掉。最後,我在ucos bsp的開始處,新增了關中斷的**,直到第乙個任務開始執行,才開啟中斷,錯誤就不再傳送了。
這個錯誤其實很簡單,但我開始並沒有解決,有很多原因:時間很緊、對板卡控制器了解過少,驗證缺乏良好的思路等等。但最直接的原因,是我在發現這個數碼管錯誤時,有了錯誤的猜想,我認為是記憶體控制器或者mmu的問題,沒有想到是因為異常沒有處理。所以說,我們習慣懷疑那些自己不確定不了解的因素,而對自己了解的熟悉的因素視而不見。很多奇奇怪怪的現象,其實只是因為很簡單的原因;很多你認為不可救藥的程式,其實只需要修改很微小的地方就可以全線暢通。
這些我在除錯過程中發現的人性的缺點,其實並非無解。因為無論在除錯過程中走過多少彎路,只要肯花時間,實驗、猜想、驗證,都總能找到一條出路。這大概就是勤能補拙吧。
RSLidar除錯過程
一 上位機除錯 windows版為硬碟版,免安裝,執行bin目錄下rsview.exe ubuntu下執行sh啟動指令碼執行 注意事項 1.速騰雷射預設的ip為192.168.1.200,目的位址為192.168.1.102。如與實際不一致,可通過wireshark抓包看一下。將本機位址改到目的ip...
windows Service 之除錯過程
最近第一次用c 寫了乙個windows service 其實實現的內容比較簡單。就是啟動remoting 連線,但是除錯相對初次寫windws service 的我來說,比較煩。沒有經驗,而且沒辦法像除錯其他windows 程式一樣設定斷點,無法看到執行過程。經過檢視一些相關資料後,有了一點點除錯的...
ExtJS新手除錯過程
本文是個人學習extjs除錯程式心得,有錯請指正,謝謝指教!寫這篇文章的初衷是因為學習extjs有了大半年的時間,從問問題到可以解答一些常識性問題過程中意識到,很多新手在問問題的時候都只是問結果為什麼不是想的那樣,包括我自己剛開始。其實問問題是一門又學問的事,知道問題點在那裡在去問 這樣可以事半功倍...