Page 46 - MCU大廠分享10億級出貨秘訣
P. 46
42
程式也能更容易通過安全認證,這 相當於更高的程式碼品質意謂在重 複使用時「技術負債」會比較少。
目前程式編碼方面已有許 多標準,但被廣泛採行的僅有少 數。MISRA C是汽車產業軟體可靠 性協會制定的C語言開發標準,其 目標是促進嵌入式系統的程式碼安 全 性、可 移 植 性,以 及 可 靠 性,尤 其 是採用ISO C標準所開發的系統。
言的規則明定若沒有宣告原型,所 有引數就會轉換成整數格式。如果 MCU沒有浮點運算單元,就會導致 進行型別轉換(casting),以及浮點 運算作業。正因如此,永遠都應宣 告函數原型,然而CWE的主要用 意在於找出有風險與不良的程式 編碼行為。
uint16_t告知編譯器變數是不帶 正負號的16位元數值,因為長度和 正負號都在變數類型中明確宣告, 並加入到stdint.h。
現有的程式編碼標準
另一項有意思的指引是rule 13,規定AND或OR邏輯運算元的 右側不能有副作用(side-effect)。 圖2的程式片斷看似完全正確,實 則不然。
MISRA C標準的第一版《車載 軟體C語言使用指引》於1998年發 表,正式名稱為MISRA C:1998。之 後於2004年更新,並於2012年加入 更多規則。另外,還根據C++ 2003 標準制定了MISRA C++ 2008規範。
SEI CERT C與C++亦定義常 見漏洞,這些項目來自實際案例研 究,像是檢查浮點數的越界(out- of-bound)狀態,以及確保你沒有 覆寫常數。此外還列出程式編碼的 風格慣例,讓程式碼更有可讀性讓 其他人能夠看懂。
問題在於左邊表述式必須是 偽(false),才會執行右側的表述, 只有在這個時候pointer p會是後 置遞增(post-incremented)。然而 問題是在撰寫程式碼時很容易弄錯 這項行為,其他人在審閱、測試、或 維護程式碼時都必須瞭解你在寫程 式時遵循的條件判斷式。這部分的 程式碼加上註解當然有助於其他人 瞭解判斷邏輯,但實務上一般很少 看到程式會載明詳細的註解。
此外,MITRE的CWE通用缺 陷列表亦規範完善的程式編碼標 準。mitre.org組織的人員執行一項 調查,希望找出開發者意外注入程 式碼的缺陷屬於什麼種類。出乎意 料的是,所有領域的開發者——包 括網頁、app、桌面、或嵌入式系 統——都傾向於犯相同種類的錯 誤。因此該組織歸納出通用缺陷 列表,列出開發者應避開的這些常 見疏失。舉例來說,C++程式碼(或 甚至C程式碼)配置資源之後沒有 釋出。另外則是沒有宣告函數原型 (prototyping)就使用函數,這點 也是良好編碼策略中一項值得關 注的議題。
業界廣泛採用MISRA C 2012 標準,據此確保各種嵌入式應用的 程式碼品質。本文剖析一些規則與 指引,藉此認識程式編碼標準對程 式碼造成的影響。
MISRA C 2012的實務範例
如果沒有宣告函數原型,在編 譯時就不會嚴格檢查型別,產生的 程式執行效率會比較差,因為C語
大 多 時 候,開 發 者 會 使 用
圖3:MISRA C 2012-rule 14程式碼範例。
www.eettaiwan.com | 2022年6月
以Directive 4.6指引為例, 規定不允許使用基本資料型別 (primitive data type),一開始這 項規定看似很奇怪,但瞭解背後 的理由後就完全了解理該如此。不 同編譯器處理整數等類型資料的 方式不盡相同,包括大小長度,以 及符號類型的規範都不一致,這也 導致審核程式碼的工作相當棘手。 如果你是審核者,難免會質疑程式 原始作者是否瞭解編譯器會如何解 譯程式碼。如果不使用基本資料型 別,就會讓程式碼在不同編譯器與 架構之間維持不變性(invariant)。
圖2:MISRA C 2012-rule 13程式碼範例。
DESIGN CORNER