緩解可查錯性問題的手段——單元測試

從本月初開始,我加入了某站開發團隊。儘管我在通訊行業工作快10年了,但這是頭一次工作於機站項目,所需學習的東西自然很多,還是那句話 — 有挑戰纔會有進步。在此我想與讀者分享過去三週我就軟件的可查錯性的一點新體會。

現從事的項目是真正的嵌入式系統,機站上的MAC和PHY程序是運行在DSP之上的。加入團隊伊始,同事告訴我,團隊在碰到Crash這樣的問題時,顯得很是被動。經過我倆幾番的交談,我得知當DSP出現crash時,工程師無法輕鬆地獲得當時的調用棧(call stack)。當時我想,“哇,盡然會出現DSP發生crash時無法以日誌的形式輸出調用棧的問題。看看我能否在這方面做點貢獻”。於是呼,加入團隊之初我就開始閱讀所用DSP的相關資料。

除了學習,還得從事一些具體的工作。我被分配從事機站程序優化方面的工作,以使機站在滿足用戶一定數據速率的情況下能支持更多的用戶。其中,我選擇了去除項目所不需要的某特性(feature)的代碼。當我將該特性從代碼中移除後,交給同事做Sanity Test,結果發現程序會出現crash。

由於我正好關注DSP在crash時的可查錯性問題,於是我借這一機會將前人留下的文檔好好地讀了一遍,加上同事的幫助,很快實踐了一下現有的查錯手段,且最終找到了引起crash的根源。

結合實踐與DSP資料的閱讀,我發現要在現有DSP上改善出現crash時的可查錯性問題還真不是一件易事,其中最大的瓶頸在於DSP本身。在大多象x86、ARM這樣的處理器上,C函數之間的調用會通過棧幀的形式形成調用棧,棧幀是由編譯器生成的代碼創建和使之消亡的。也正是因爲調用棧的存在,使得當程序出現crash時,通過在中斷(或異常)服務程序中回朔調用棧的方式獲得函數調用關係以便我們找查錯。然而,在DSP上,只有當以-g選項編譯調試版本的程序時,編譯器才生成代碼爲每一個函數創建棧幀,這樣做的目的是爲了更方便的調試。一旦不使用-g選項,DSP並不一定爲每一個函數形成棧幀。

讀者或許會想,爲什麼不在出現crash時用調試版本的程序幫助查錯呢?其一,調試版本的程序在性能上達不到產品的要求,甚至可能使得產品的功能根本就不能正常工作(查錯無從下手)。其二,調試版本的程序由於沒有優化過,所以所需佔用的文件存儲空間更大。在我們的項目中,據說調試版本的程序文件因爲閃存空間有限根本無法放入機站中。最後,使用調試版本的程序有時無法復現問題。

在軟件開發期間出現上述可查錯性問題在嵌入式軟件開發領域是一種很常見的現象,在技術上無法很好地解決可查錯問題時,我們應如何應對?單元測試或許是一條不錯的出路!前面提到的crash問題,其實如果我做單元測試的話可以很輕鬆地發現問題,因爲問題的根源是沒有對變量指針進行初始化。

說到單元測試,或許會讓不少人頭痛 — 太浪費時間!這種觀點多少有些主觀,因爲單元測試能爲我們節省用於查錯的時間,且幫助我們規避查錯壓力從而更從容地開展開發活動。單元測試的實施首先不是成本問題,而是意識和習慣問題!

幸運的是,現有的項目部署了單元測試。熟悉已有的單元測試環境是下一件我想去做的事。
 
本文出自李雲的博客,請務必保留此出處:http://blog.csdn.net/hzliyun/article/details/7833137。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章