一、MISRA C與C語言
自1972年Dennis MacAlistair Ritchie在美國貝爾實驗室創造C語言以來,它已成為當今最流行的編程語言之一。C語言以其使用的靈活性、功能的豐富性而廣受歡迎,但同時也因其寬松的語法和不嚴格的數據類型給開發的產品帶來了安全隱患。
1989年,ANSI發布了C89標準,標志著C語言標準化的重要一步。隨后,C99標準在1999年發布,引入了多項新特性,如幾類新的數據類型和更強大的字符串處理功能。
隨著嵌入式系統在汽車行業的廣泛應用,英國政府于90年代初啟動了“SafeIT”研究計劃,旨在為道路車輛電子系統的嵌入式軟件開發制定安全指南。這份文件具有重要意義,代表了行業共識,也是汽車行業第一種功能安全方法,比國際層面的ISO 26262工作開始早了大約10年。
由汽車工業軟件可靠性協會(Motor Industry Software Reliability Association,即MISRA)制定的一套針對于C語言的編碼規范,作為響應該指南的產物,為汽車行業提供了一種功能安全方法,MISRA C由此誕生。
MISRA C規范包括一系列規則和指導原則,分為強制規范(Mandatory guidelines)、要求規范(Required guidelines)和建議規范(Advisory guidelines)。這些規范覆蓋了編程實踐、代碼設計等多個方面,旨在幫助開發者編寫出更加安全和可靠的代碼。
MISRA C規范包含以下核心原則:
?1、未定義行為的限制(Undefined Behavior)
MISRA C通過制定規則來限制數組越界、指針解引用等未定義行為。例如,規則指導開發者避免使用未初始化的指針,以及確保數組索引不會超出其界限。
例如:Dir 4.12?????? Dynamic memory allocation shall not be used.
代碼如下:
#include <stdlib.h>
void f ( void )
{
char *p = ( char * ) malloc ( 10 );
char *q;
free( p );
q = p;????????? /* 未定義行為 —— 此時p的值不確定 */
p = ( char * ) malloc ( 20 );
free( p );
p = NULL?????? /* 將釋放的指針賦值為NULL —— 此時p的值為確定 */
}
?2、類型安全(Type Safety)
MISRA C強制類型匹配和顯式類型轉換,以增強代碼的類型安全性。例如,它要求在進行隱式類型轉換時必須進行適當的檢查,以避免數據丟失或意外行為。
C語言不要求強制檢查所有的顯示轉換,允許不兼容的類型之間進行轉換。
比如在不考慮數據容量的情況下,整型數據間的隱式轉換可以參考下面的表格。
(Note:si——有符號32位;ui——無符號32位;uc——無符號8位)
表達式 | 變格 | 符號平衡 | 變換 | 說明 |
si = si + si; | ||||
si = uc + uc; | 是 | uc的符號變格為有符號32位 | ||
ui =si + ui; | 是 | si的符號平衡為無符號32位 | ||
ui = ui + uc; | 是 | 是 | uc的符號變格為有符號32位再平衡為無符號32位 | |
ui = si; | 是 | si的符號變換為無符號32位 | ||
ui = uc + uc; | 是 | 是 | uc的符號變格為有符號32位后結果變換為無符號32位 | |
si = si +ui; | 是 | 是 | si的符號平衡為無符號32位后結果變換為有符號32位 | |
si = ui +uc; | 是 | 是 | 是 | uc的符號變格為有符號32位,平衡為無符號32位后結果為有符號32位 |
3、資源管理(Resource Management)
MISRA C強調正確管理內存分配和釋放,避免內存泄漏。它提供了關于動態內存分配的最佳實踐,包括何時使用以及如何正確釋放內存。
分配內存的常用的標準庫函數是malloc,對應釋放內存的是free。
例如:Rule 22.2???? A block of memory shall only be freed if it was allocated by means of a Standard Library function。
#include <stdlib.h>
void fn ( void )
{
int a;
free(&a); /* NG——此內存空間不是有庫函數分配 */
}
void g ( void )
{
??????? char *p = ( char *)malloc(512);
??????? char *q = p; /* 兩個指針指向同一空間 */
??????? free( p );? /* OK——通過p指針,內存第1次釋放 */
??????? free( q );? /* NG——通過q指針,內存第2次釋放 */
}
?4、函數與宏的使用(Function and Macro Usage)
MISRA C推薦優先使用函數而非宏,以減少錯誤。它還規定了函數的返回類型和參數使用,以增強代碼的可讀性和可維護性。例如,建議使用返回類型為void的函數來執行操作,而不是返回狀態碼。
例如:Dir 4.9 A function should be used in preference to a function-like where they are interchangeable.
另外,在代碼調試的時候,函數可以進行單步調試,有利于發現問題,反而宏就沒有這個優勢了。
?5、控制流(Control Flow)
MISRA C對控制流語句使用有嚴格規定,限制’goto’語句,鼓勵使用結構化控制語句如`if`、`while`和`for`循環。
例如:Rule 15.1???? The goto statement should be used
在開發設計時,所有的數據流都已經明確的情況下,則可以禁止引入’goto’。
?6、錯誤處理(Error Handling)
MISRA C提供錯誤處理指導,幫助開發者以一致和可預測的方式處理錯誤。例如,它建議使用標準化的錯誤代碼和清晰的錯誤處理流程。
?7、可移植性(Portability)
MISRA C鼓勵使用可移植的代碼實踐,避免依賴特定編譯器或平臺特性。這包括使用標準庫函數和避免平臺特定的擴展。
?8、代碼風格與格式化(Coding Style and Formatting)
雖然主要關注安全性和可靠性,MISRA C也提供了代碼風格和格式化的建議,以提高代碼的可讀性。這包括命名約定、縮進和注釋的使用。
二、MISRA C++——MISRA C的繼承
1978年,一門新型開發語言同樣誕生于美國貝爾實驗室,這門開發語言就是C++。
說到MISRA C++的發展歷史,AUTOSAR C++是一個繞不過去的關鍵點。
眾多汽車廠商于2003年組建了AUTOSAR開發聯盟,發布了汽車開放系統架構(Automotive Open Software Architecture,即AUTOSAR)和經典平臺(Classic Platform),后期為了滿足高度自動駕駛和汽車互聯應用的快速發展,于2017年發布了第一個版本的自適應平臺(Adaptive Platform),至此也決定了C++的領先地位。
隨著汽車系統的復雜化加深,C++已經處于曾經C語言的高度。但多數人認為,C++不應該用于關鍵系統。因此,一套類似于“MISRA C”、適用于C++的指導于2008年發布。這就是MISRA C++的初版,也就是MISRA C++:2008。
AUTOSAR C++:14規范是基于MISRA C++:2008進行補充完善的,填補 C++11和C++14 在關鍵和安全相關軟件中使用時缺乏適當編碼標準的空白。
MISRA C++:2023 是 MISRA C++ 標準的下一個版本,它將整合 AUTOSAR C++:14 規范,并支持 C++ 的最新版本,是汽車行業和其他使用嵌入式系統行業的最佳標準之一。
MISRA C++ 標準包含一系列的規則和指導原則,它們分為不同的類別,如強制性、推薦性等。這些規則幫助開發者避免使用可能導致不安全或不可預測行為的語言特性,同時鼓勵使用那些能夠提高代碼質量和可維護性的編程實踐。
MISRA C++:2023 標準的特點包括:
整合了 AUTOSAR C++:14規范,共有 179 條準則。
規則按照性質分為兩類:Rule(規則)和 Directive(指令),包含 175 條 Rule 和 4 條 Directive。
支持C++的最新特性,同時確保代碼的安全性和可靠性。
MISRA C++標準的使用可以提高嵌入式系統的安全性和可移植性,特別是在那些對安全性要求極高的應用中。通過遵循這些指南,開發者可以減少編程錯誤,提高代碼質量,確保軟件系統的穩定性和可靠性。
三、MISRA C、MISRA C++與靜態測試
靜態測試是軟件測試的一種方法,它不涉及程序的執行,而是通過分析源代碼來檢測潛在的錯誤和代碼質量問題。MISRA C、MISRA C++與靜態測試緊密相關,因為 MISRA C、MISRA C++標準提供了一套規則和指南,靜態測試工具可以使用這些規則來自動檢測代碼是否符合 MISRA C、MISRA C++標準。
使用靜態測試工具來執行MISRA C、MISRA C++標準的檢查可以帶來以下好處:
1. 早期發現缺陷:在編碼階段就能發現潛在的問題,減少后期修復的成本和復雜性。
2. 提高代碼質量:確保代碼遵循行業認可的最佳實踐,提高軟件的整體質量和可靠性。
3. 符合行業標準:對于需要遵守特定行業安全標準的項目,如汽車行業的 ISO 26262,靜態測試可以幫助確保代碼符合這些標準。
4. 自動化:自動化的代碼分析可以節省時間,減少人為錯誤,提高開發效率。
5. 一致性:確保整個項目或團隊遵循統一的編碼標準,提高代碼的一致性和可維護性。
總的來說,MISRA C、MISRA C++與靜態測試的結合為嵌入式系統的軟件開發提供了一種高效且可靠的質量保證方法,有助于提升軟件安全性并減少風險。
目前市場上靜態測試工具有很多,PC-lint Plus是Vector公司出品的一套全面的、輕量級的C/C++代碼靜態分析工具。
在MISRA C方面,PC-lint Plus提供對MISRA C:2012規范及上一代版本MISRA C:2004規范的支持,在MISRA C++方面,PC-lint Plus提供AUTOSAR C++規范及后續的MISRA C++規范的支持。
這種支持通過標準PC-lint Plus消息和專用于特定MISRA規則的可選性來實現。如果大家有該方面的需求,可以直接留言或聯系郵箱market@dotrustech.com。