嵌入式開發(fā)人員經(jīng)常抱怨沒有一種編程語(yǔ)言適合他們的特殊需求。在某種程度上,這種情況并不令人驚訝,因?yàn)楸M管許多開發(fā)人員都在開發(fā)嵌入式應(yīng)用程序,但他們?nèi)匀恢皇鞘澜缇幊躺鐓^(qū)的一小部分。盡管如此,有些語(yǔ)言的開發(fā)還是考慮到了嵌入式。值得注意的例子是PL/M、Forth和Ada,它們都被廣泛使用,但從未被普遍接受。其他語(yǔ)言,如Rust,正在獲得支持,但尚未成為主流。幾乎被普遍采用的折衷方案是C,如何使折衷方案最有效地發(fā)揮作用?
C語(yǔ)言結(jié)構(gòu)緊湊,表達(dá)能力強(qiáng),功能強(qiáng)大。它為程序員提供了編寫高效、可讀和可維護(hù)代碼的方法。所有這些特性都是它受歡迎的原因。不幸的是,這種語(yǔ)言還使粗心大意的開發(fā)人員編寫危險(xiǎn)的、不安全的代碼,這些代碼在開發(fā)項(xiàng)目的所有階段和部署中都可能導(dǎo)致嚴(yán)重的問題。對(duì)于安全性和/或安全性是主要優(yōu)先事項(xiàng)的應(yīng)用程序,語(yǔ)言的這些缺點(diǎn)是一個(gè)主要問題。
正是在這種背景下,在20世紀(jì)90年代末,汽車工業(yè)軟件可靠性協(xié)會(huì)(MISRA)推出了一套關(guān)于在車輛系統(tǒng)中使用C的指南,稱為MISRA
C~自那時(shí)以來(lái),該指南一直在不斷完善,并不時(shí)發(fā)布更新。還建立了類似的使用C++的方法。雖然該指南最初是針對(duì)汽車用軟件的嵌入式開發(fā)人員,但很快就意識(shí)到,它們同樣適用于安全性至關(guān)重要的許多其他應(yīng)用領(lǐng)域,并且該標(biāo)準(zhǔn)現(xiàn)在已在許多行業(yè)中廣泛采用。
盡管MISRA
C不是一個(gè)樣式指南——事實(shí)上,許多用戶應(yīng)用了樣式指南和標(biāo)準(zhǔn)——但許多規(guī)則也促進(jìn)了清晰易讀的可維護(hù)代碼的編寫。這是非常有益的,因?yàn)橐子诶斫獾拇a不太可能隱藏細(xì)微的錯(cuò)誤或未定義的行為。
我將在這里簡(jiǎn)單介紹一下指南。MisraC正在不斷地進(jìn)行審查,不斷地修改指南的清晰性和準(zhǔn)確性,并支持更新版本的C語(yǔ)言標(biāo)準(zhǔn)。盡管細(xì)節(jié)發(fā)生了變化,但總體理念和方法沒有變化。
規(guī)則13.2–在所有允許的評(píng)估順序下,表達(dá)式的值及其持續(xù)性副作用應(yīng)相同
C語(yǔ)言標(biāo)準(zhǔn)在表達(dá)式的求值順序方面為編譯器提供了非常廣泛的自由度。因此,在嵌入式開發(fā)中,任何對(duì)求值順序敏感的代碼都依賴于編譯器,并且依賴于編譯器的代碼應(yīng)始終被視為不安全的。
規(guī)則17.2——職能部門不得直接或間接地調(diào)用自己
有時(shí),表達(dá)算法的一種優(yōu)雅方式是使用遞歸。但是,除非遞歸受到非常嚴(yán)格的控制,否則存在堆棧溢出的危險(xiǎn),這反過來(lái)會(huì)導(dǎo)致很難找到bug。在安全關(guān)鍵代碼中,應(yīng)避免遞歸。
規(guī)則19.2–不應(yīng)使用union關(guān)鍵字
盡管C是一種類型化語(yǔ)言,但類型化并不是很嚴(yán)格,開發(fā)人員可能會(huì)試圖覆蓋類型化來(lái)“簡(jiǎn)化”代碼。遵守?cái)?shù)據(jù)類型的約束對(duì)于創(chuàng)建安全代碼至關(guān)重要,因?yàn)槿魏卫@過數(shù)據(jù)類型的嘗試都可能產(chǎn)生未定義的結(jié)果。union關(guān)鍵字可以用于多種目的,通常會(huì)導(dǎo)致代碼不清晰,但也可以作為避免鍵入的一種手段。
有人可能會(huì)爭(zhēng)辯說,這些規(guī)則(以及MisraC的大部分,如果不是全部的話)只是常識(shí),任何優(yōu)秀的嵌入式開發(fā)人員都會(huì)采用這種方法。這可能是真的,但一套明確的指導(dǎo)方針讓機(jī)會(huì)更少了。