所有重要的軟件都有錯誤。我不想稱它們?yōu)椤板e誤”,因為這會使它們與需要為自己的錯誤負(fù)責(zé)的開發(fā)人員分離。顯然,設(shè)計良好的軟件可能會更少,而現(xiàn)代嵌入式軟件開發(fā)工具的應(yīng)用可以將它們保持在最低限度。當(dāng)然,具體的錯誤無法預(yù)測(否則它們可以被根除),但是可以識別某些類型的軟件問題,并且有可能在問題變成災(zāi)難之前發(fā)現(xiàn)問題。
我會將此類軟件問題分為兩大類:
數(shù)據(jù)損壞
代碼循環(huán)
由于大量嵌入式代碼是用 C 編寫的,這意味著開發(fā)人員很可能會使用指針。小心使用,指針是該語言的一個強大功能,但它們也是最常見的程序員錯誤來源之一。指針使用的問題很難靜態(tài)識別,并且引入的錯誤可能會在代碼執(zhí)行時以微妙的方式表現(xiàn)出來。有些事情,比如取消引用空指針很容易檢測到,因為它們通常會導(dǎo)致陷阱。只需要實現(xiàn)一個陷阱處理程序。其他的更難,因為指針最終可能指向任何地方——通常它會指向一個有效的地址,但不幸的是,它可能不是正確的地址。自測試代碼對此幾乎無能為力。然而,有兩種特殊但非常常見的,
不應(yīng)發(fā)生堆棧溢出,因為應(yīng)仔細(xì)確定堆棧分配,并在調(diào)試階段驗證其使用情況。但是,很可能會忽略不尋常的情況或使用不易測試的構(gòu)造(如遞歸函數(shù))。一個簡單的解決方案是在堆??臻g的任一端包含一個額外的詞——“保護詞”。這些預(yù)加載了特定值,由自檢任務(wù)(可能在后臺運行)監(jiān)控。如果值更改,則違反了堆棧限制。應(yīng)謹(jǐn)慎選擇該值。奇數(shù)是最好的,因為它不代表大多數(shù)處理器的有效地址。也許是 0x55555555。只要該值“不太可能”——例如不是 0x00000001 或 0xffffffff——就有 40 億比 1 的機會發(fā)生誤報。
在某些語言中,存在用于在數(shù)組邊界之外尋址的內(nèi)置檢測,但這會引入運行時開銷,這可能是不受歡迎的。因此,這不是在 C 中實現(xiàn)的。此外,可以使用指針而不是運算符來訪問數(shù)組元素,因此可能會規(guī)避任何檢查。最好的方法是通過在數(shù)組末尾定位一個保護字并以與堆棧溢出檢查相同的方式進行監(jiān)視來檢查緩沖區(qū)溢出類型的錯誤。
在這兩種情況下,當(dāng)保護字被破壞時,這表明即將發(fā)生故障。堆棧或數(shù)組可能只是一個字就溢出或不足,因此還沒有造成真正的損害。定位錯誤訪問的原因比調(diào)試可能發(fā)生的隨機崩潰要容易得多。
代碼永遠(yuǎn)不應(yīng)陷入無限循環(huán),但邏輯錯誤或未發(fā)生預(yù)期的外部事件可能會導(dǎo)致代碼掛起。當(dāng)代碼在等待某事發(fā)生時,理想情況下應(yīng)該有一個超時機制,這樣代碼就不會無限期地掛起。
在任何類型的多線程環(huán)境中——無論是 RTOS 還是帶有 ISR 的主線代碼——都可以實現(xiàn)“看門狗”機制。每個連續(xù)運行的任務(wù)(可能只是主線代碼)都需要每隔一段時間與看門狗任務(wù)(可能是計時器 ISR)“簽入”。如果發(fā)生超時,則需要采取措施。
那么,當(dāng)檢測到堆棧溢出、數(shù)組綁定違例或掛起任務(wù)時該怎么辦呢?這取決于應(yīng)用程序。可能只需要停止和重新啟動單個任務(wù),但可能需要更激烈的操作:停止系統(tǒng)、發(fā)出某種警報或簡單地重置系統(tǒng)。選擇取決于許多因素,但從廣義上講,目標(biāo)是為了比崩潰的系統(tǒng)更好的東西。
訂閱
審核編輯:郭婷
-
嵌入式
+關(guān)注
關(guān)注
5054文章
18917瀏覽量
300988 -
RTOS
+關(guān)注
關(guān)注
21文章
808瀏覽量
119304 -
代碼
+關(guān)注
關(guān)注
30文章
4700瀏覽量
68111
發(fā)布評論請先 登錄
相關(guān)推薦
評論