在實(shí)驗(yàn)室中起作用的東西并不總是在現(xiàn)場(chǎng)起作用,這通常是由于意外的交互和未發(fā)現(xiàn)的錯(cuò)誤。防御性編程有助于使設(shè)計(jì)更具彈性,但開發(fā)能夠處理不可預(yù)見情況的嵌入式軟件并非易事,這需要紀(jì)律和深謀遠(yuǎn)慮。這里有五個(gè)技巧可以幫助嵌入式開發(fā)人員成為更好的防御性程序員。
技巧1——校驗(yàn)和或 CRC 數(shù)據(jù)
使用校驗(yàn)和和循環(huán)冗余校驗(yàn) (CRC) 算法是開發(fā)人員驗(yàn)證通過串行鏈路發(fā)送的數(shù)據(jù)確實(shí)是否正確的一種好方法。經(jīng)過審查的嵌入式系統(tǒng)在測(cè)試平臺(tái)的受控環(huán)境中將始終按預(yù)期運(yùn)行。然而,一旦系統(tǒng)被釋放到野外,系統(tǒng)運(yùn)行的環(huán)境就變得非常未知。嘈雜的環(huán)境可能會(huì)產(chǎn)生通信噪聲,從而導(dǎo)致位翻轉(zhuǎn)和誤讀數(shù)據(jù)。檢測(cè)這些損壞數(shù)據(jù)的最大希望是通過使用校驗(yàn)和或 CRC 對(duì)數(shù)據(jù)進(jìn)行完整性檢查。
技巧2——契約式設(shè)計(jì)
契約式設(shè)計(jì)是一種開發(fā)軟件的方法,它產(chǎn)生高度定義的軟件接口,其中每個(gè)功能都與明確定義的前置條件和后置條件相關(guān)聯(lián)。這個(gè)想法是,如果應(yīng)用程序要調(diào)用特定函數(shù),調(diào)用的應(yīng)用程序必須滿足函數(shù)的先決條件才能獲得有效的響應(yīng)或操作。契約式設(shè)計(jì)對(duì)于開發(fā)人員來說是一個(gè)強(qiáng)大的工具,因?yàn)樗鞔_地指定了函數(shù)期望接收的內(nèi)容以及在有效前提條件下保證的輸出將是什么。由于期望不是“從字里行間讀取”,調(diào)用該函數(shù)的嵌入式開發(fā)人員確切地知道為了使用該函數(shù)而期望是什么。
技巧3——使用斷言
斷言宏是開發(fā)人員在應(yīng)用程序中的給定時(shí)刻驗(yàn)證他們對(duì)應(yīng)用程序的假設(shè)的好方法。斷言的使用對(duì)于在錯(cuò)誤發(fā)生的那一刻捕捉程序中的錯(cuò)誤和意外行為非常有效。斷言甚至可以在按契約式設(shè)計(jì)的環(huán)境中使用,以驗(yàn)證契約的前置條件和后置條件是否得到滿足。
技巧4——檢查指針和緩沖區(qū)
指針和緩沖區(qū)是開發(fā)人員似乎總是讓自己陷入麻煩的兩個(gè)地方。在用C開發(fā)嵌入式系統(tǒng)時(shí),很容易意外地取消對(duì)空指針的引用或溢出緩沖區(qū)。防御性的程序員應(yīng)該在取消引用一個(gè)指針之前檢查它的有效性。指針是否為空?不要取消引用它!指針中存儲(chǔ)的值是有效值嗎?如果是,則取消引用。
指針?biāo)惴ê蛿?shù)組的使用也非常危險(xiǎn)。嵌入式開發(fā)人員應(yīng)該在緩沖區(qū)和指針?biāo)阈g(shù)運(yùn)算中添加邊界檢查,以確保結(jié)果保持在它們應(yīng)該在的內(nèi)存空間內(nèi)。意外地覆蓋一個(gè)字節(jié)的內(nèi)存可能會(huì)給嵌入式系統(tǒng)帶來災(zāi)難性的后果,更重要的是,會(huì)給用戶帶來災(zāi)難性的后果。
技巧5——使用堆棧監(jiān)視器
執(zhí)行最壞情況下的堆棧分析并正確確定堆棧大小是一項(xiàng)艱巨的任務(wù)。通常堆棧的大小要么保留編譯器的默認(rèn)設(shè)置,要么開發(fā)人員在一張紙上草草寫下一些可能的值,并使用“eeny meeny miny moe”技術(shù)。這兩種技術(shù)都不充分,最壞的情況是堆棧溢出。
開發(fā)人員可以通過監(jiān)視此類事件來幫助防止堆棧溢出。大多數(shù)實(shí)時(shí)操作系統(tǒng)都內(nèi)置了堆棧監(jiān)視器。啟用堆棧監(jiān)視器只不過是用RTOS的配置來調(diào)整宏。在裸機(jī)系統(tǒng)中,開發(fā)人員需要更加積極主動(dòng),要么自己編寫一個(gè)堆棧監(jiān)視器,要么使用互聯(lián)網(wǎng)上提供的許多堆棧監(jiān)視器中的一個(gè)。
最后的想法
這五個(gè)技巧只是嵌入式開發(fā)人員如何通過防御性編程來改進(jìn)嵌入式軟件的幾個(gè)例子。還有許多其他技術(shù),如編寫安全代碼和加密數(shù)據(jù),可以幫助提高嵌入式系統(tǒng)在不可預(yù)見的情況下繼續(xù)運(yùn)行的機(jī)會(huì)。