講到系統穩定性,人們更多地會想到實時性和速度,因為代碼效率對嵌入式系統來說太重要了。知道怎么優化代碼是每個嵌入式軟件開發人員必須具備的技能。就象女孩子減肥一樣,起碼知道她哪個地方最需要減,才能去購買減肥藥或器材來減掉它?梢,代碼優化的前提是找到真正需要優化的地方,然后對癥下藥,優化相應部分的代碼。前面提到的profile(性能分析工具,一些功能齊全IDE都提供這種內置的工具)能夠記錄各種情況比如各個任務的CPU占用率、各個任務的優先級是否分配妥當、某個數據被拷貝了多少次、訪問磁盤多少次、是否調用了網絡收發的程序、測試代碼是否已經關閉等等。
但是,profile工具在分析實時系統性能方面還是有不夠的地方。一方面,人們使用profile工具往往是在系統出現問題即CPU耗盡之后,而profile工具本身對CPU占用較大,所以profile對這種情況很可能不起作用。根據Heisenberg效應,任何測試手段或多或少都會改變系統運行,這個對profiler同樣適用! 總之,提高運行效率的前提是你必須要知道CPU到底干了些什么干的怎么樣。
4.不要讓自己大海撈針
大海撈針只是對調試的一種生動比喻。經常聽到組里有人對自己正在調試的代碼說shit!可以理解,因為代碼不是他寫的,他有足夠的理由去shit bug百出的代碼,只要他自己不要寫出這種代碼,否則有一天同組的其它人可能同樣會shit他寫的代碼。為何會有大海撈針呢?肯定是有人把針掉到海里咯;那針為何會掉在海里呢?肯定是有人不小心或草率唄。所以當你在抱怨針那么難找的時候,你是否想過是你自己草率地丟掉的。同樣,當你調試個半死的時候,你是否想過你要好好反省一下當初為了尋求捷徑可能沒有嚴格地遵守好的編碼設計規范、沒有檢測一些假設條件或算法的正確性、沒有將一些可能存在問題的代碼打上記號呢?
如果你確實已經把針掉在海里是,為了防止在找到之前刺到自己,你必須要做一些防范工作,比如戴上安全手套。同樣,為了盡能地暴露和捕捉問題根源,我們可以設計比較全面的錯誤跟蹤代碼。怎么來做呢?盡可能對每個函數調用失敗作出處理,盡可能檢測每個參數輸入輸出的有效性包括指針以及檢測是否過多或過少地調用某個過程。錯誤跟蹤能夠讓你知道你大概把針掉在哪個位置。
5.重現并隔離問題
如果你不是把針掉在大海了,而是掉在草堆里,那要好辦些。因為至少我們可以把草堆分成很多塊,一塊一塊的找。對于模塊獨立的大型項目,使用隔離方法往往是對付那些隱藏極深bug的最后方法。如果問題的出現是間歇性的,我們有必要設法去重現它并記錄使其重現的整個過程以備在下一次可以利用這些條件去重現問題。如果你確信可以使用記錄的那些條件去重現問題,那么我們就可以著手去隔離問題。怎么隔離呢?我們可以用#ifdef把一些可能和問題無關的代碼關閉,把系統最小化到仍能夠重現問題的地步。如果還是無法定位問題所在,那么有必要打開“工具箱”了?梢栽囍肐CE或數據監視器去查看某個可疑變量的變化;可以使用跟蹤工具獲得函數調用的情況包括參數的傳遞;檢查內存是否崩潰以及堆棧溢出的問題。
6.以退為進
獵人為了不使自己在森林里迷路,他常常會在樹木上流下一些標記,以備自己將來有一天迷路時可以根據這些標記找到出路。對過去代碼的修改進行跟蹤記錄對將來出現問題之后的調試很有幫助。假如有一天,你最近一次修改的程序跑了很久之后忽然死掉了,那么你這時的第一反映就是我到底改動了些什么呢,因為上次修改之前是好的。那么如何檢測這次相對于上次的修改呢?沒錯,代碼控制系統SCS或稱版本控制系統VCS(Concurrent Version Control,CVS是VCS的演化版本)。將上個版本check in下來后和當前測試版本比較。比較的工具可以是SCS/VCS/CVS自帶的diff工具或其它功能更強的比較工具,比如BeyondCompare和ExamDiff。通過比較,記錄所有改動的代碼,分析所有可能導致問題的可疑代碼。
7.確定測試的完整性
你怎么知道你的測試有多全面呢?覆蓋測試(coverage testing)可以回答這個問題。覆蓋測試工具可以告訴你CPU到底執行了那些代碼。好的覆蓋工具通?梢愿嬖V你大概20%到40%代碼沒有問題,而其余的可能存在bug。覆蓋工具有不同的測試級別,用戶可以根據自己的需要選擇某個級別。即使你很確信你的單元測試已經很全面并且沒有dead code,覆蓋工具還是可以為你指出一些潛在的問題,看下面的代碼:if (i >= 0 && (almostAlwaysZero == 0 || (last = i)))如果almostAlwaysZero為非0,那么last=i賦值語句就被跳過,這可能不是你所期望的。這種問題通過覆蓋工具的條件測試功能可以輕松的被發現?傊,覆蓋測試對于提高代碼質量很有幫助。
8.提高代碼質量意味著節省時間
有研究表明軟件開發的時間超過80%被用在下面幾個方面:.調試自己的代碼(單元測試).調試自己和其他相關的代碼(模塊間測試).調試整個系統(系統測試)更糟糕的是你可能需要花費10-200倍的時間來找一個bug,而這個bug在開始的時候可能很容易就能找到。一個小bug可能讓你付出巨大的代價,即使這個bug對整個系統的性能沒有太大的影響,但很可能會影響讓那些你可以看得到的部分。所以我們必須要養成良好的編碼和測試手段以求更高的代碼質量,以便縮短調試的代碼。
9.發現它,分析它,解決它
這世界沒有萬能的膏藥。profile再強大也有力不從心的時候;內存監視器再好,也有無法發現的時候;覆蓋工具再好用,也有不能覆蓋的地方。一些隱藏很深的問題即使用盡所有工具也有可能無法查到其根源,這時我們能做的就是通過這些問題所表現出來的外在現象或一些數據輸出來發現其中的規律或異常。一旦發現任何異常,一定要深入地理解并回溯其根源,直到解決為止。
10.利用初學者的思維
有人這樣說過:“有些事情在初學者的腦子里可能有各種各樣的情況,可在專家的頭腦里可能就很單一”。有時候,有些簡單的問題會被想的很復雜,有些簡單的系統別設計的很復雜,就是由于你的“專家思維”。當你被問題難住時,關掉電腦,出去走走,把你的問題和你的朋友甚至你的小狗說說,或許他們可以給你意想不到的啟發。 總結:嵌入式調試也是一門藝術。就想其它的藝術一樣,如果你想取得成功,你必須具備智慧、經驗并懂得使用工具。只要我們能夠很好地領悟Oracle這十條秘訣,我相信我們在嵌入式測試方面就能夠取得成功
文章來源于領測軟件測試網 http://www.kjueaiud.com/