C++是面向?qū)ο蟮木幊?,比C語言更加復(fù)雜,抽象程度高,但C++在一些圖像處理、系統(tǒng)、控件的編程方面,實(shí)用性更強(qiáng),具有自己的編程優(yōu)勢(shì)。在車載嵌入式系統(tǒng)的開發(fā)中,C和C++都具有重要的作用。C++語言所使用的面向?qū)ο蟮木幊碳夹g(shù)如封裝、繼承和多態(tài)性極大的提高了在大規(guī)模嵌入式編程應(yīng)用中代碼的可讀性、可重用性和可移植性。C++在嵌入式系統(tǒng)中廣泛使用的主要原因包括:
- C++為許多嵌入式系統(tǒng)所必需的高速、低級(jí)輸入/輸出操作提供了良好的支持;
- 應(yīng)用程序復(fù)雜性的增加使得使用高級(jí)預(yù)語言比匯編語言更適合;
- C++編譯器可以生成與C具有相似大小和RAM要求的代碼;
- C++支持使用面向?qū)ο蟮脑O(shè)計(jì)方法;
- 在低成本硬件上移植性的要求的增長(zhǎng);
- 從建模包中自動(dòng)生成C++代碼的使用增加;
- 對(duì)開發(fā)系統(tǒng)和托管環(huán)境的興趣日益增加,C++是一種可能的語言選擇;
因此,在輔助駕駛、無人駕駛等軟件系統(tǒng)的開發(fā)中,C++被廣泛的應(yīng)用。針對(duì)C++在汽車工業(yè)領(lǐng)域的安全規(guī)范也逐漸完善。AUTOSAR C++是ISO/IEC 14882標(biāo)準(zhǔn)在汽車工業(yè)子領(lǐng)域的應(yīng)用規(guī)范。
一、AUTOSAR C++規(guī)范
AUTOSAR C++是MISRA C++:2008的更新,也是汽車工業(yè)領(lǐng)域的安全性編程規(guī)范,但AUTOSAR C++不僅限應(yīng)用于汽車工業(yè)領(lǐng)域,也可以應(yīng)用在其他的嵌入式系統(tǒng)。。在AUTOSAR C++之前,MISRA C++ 2008是C++在汽車等關(guān)鍵領(lǐng)域的編程指導(dǎo)規(guī)范。隨著C++的標(biāo)準(zhǔn)不斷的更新,MISRA C++ 2008已經(jīng)不包括對(duì)C++11/14的規(guī)范要求。AUTOSAR C++ 的一些列規(guī)范在此背景下發(fā)布,彌補(bǔ)了MISRA C++:2008的不足。在MISRA C++:2008基礎(chǔ)上,AUTOSAR C++:14的演變?yōu)椋?/p>
- C++語言的實(shí)質(zhì)性演變/改進(jìn);
- 在安全相關(guān)和關(guān)鍵環(huán)境中更廣泛的使用面向?qū)ο蟮恼Z言;
- 可用的更好編譯器;
- 提供適合C++的更好的測(cè)試、驗(yàn)證和分析工具;
- 提供更好的開發(fā)方法(如持續(xù)集成),以便更早的檢測(cè)/處理錯(cuò)誤;
- 安全工程師對(duì)面向?qū)ο蟮木幊陶Z言的接受程度更高;
- 開發(fā)團(tuán)隊(duì)對(duì)功能強(qiáng)大的C++語言特性的強(qiáng)烈需求;
- 構(gòu)建ISO 26262安全標(biāo)準(zhǔn),包括HIC++, JSF++, CERTC++,C++核心指南;
除此之外,AUTOSAR在MISRA C++:2008基礎(chǔ)之上指定了:
- 哪些MISRA C規(guī)則已經(jīng)過時(shí),不需要遵守;
- 一些更新的MISRA規(guī)則;
- 一些額外的規(guī)則;
與MISRA-C一樣,AUTOSAR C++的規(guī)范中的規(guī)則根據(jù)義務(wù)等級(jí)進(jìn)行規(guī)則劃分為:必需(強(qiáng)制性)、建議性。根據(jù)靜態(tài)分析執(zhí)行規(guī)則可以劃分為:自動(dòng)化、部分自動(dòng)化、非自動(dòng)化。絕大多數(shù)的規(guī)則都是能夠通過靜態(tài)分析自動(dòng)強(qiáng)制執(zhí)行。除此之外,這些規(guī)則還可以根據(jù)被分配的目標(biāo)分類為:實(shí)施(代碼、軟件設(shè)計(jì)、架構(gòu))、驗(yàn)證(代碼審查、分析、測(cè)試)、工具鏈(預(yù)處理器、編譯器、鏈接器、編譯器庫(kù))、基礎(chǔ)設(shè)施(運(yùn)行系統(tǒng)、硬件)。
二、AUTOSAR C++對(duì)安全性的理解
C++語言的不安全性主要來源有:開發(fā)者犯錯(cuò)、開發(fā)者對(duì)C++的誤解、編譯器不執(zhí)行開發(fā)人員所期望的操作、編譯器包含錯(cuò)誤、運(yùn)行是的錯(cuò)誤。
- 開發(fā)者犯錯(cuò):
開發(fā)人員會(huì)犯很簡(jiǎn)單的錯(cuò)誤,比如錯(cuò)誤地輸入了一個(gè)變量名,也可能會(huì)犯一些諸如誤解了一個(gè)算法這樣的復(fù)雜錯(cuò)誤。編程語言與這種類型的錯(cuò)誤有關(guān)。首先,語言的風(fēng)格和表達(dá)性可以幫助或阻礙程序員清晰地思考算法。其次,該語言可以使輸入錯(cuò)誤將一個(gè)有效的構(gòu)造變成另一個(gè)有效的(但無意的)構(gòu)造變得容易或困難。第三,編譯器在出現(xiàn)錯(cuò)誤時(shí)可能檢測(cè)到也可能不檢測(cè)到錯(cuò)誤,其主要原因如下:
首先,在風(fēng)格和表達(dá)性方面,C++可以用來編寫布局良好、結(jié)構(gòu)化和表達(dá)性強(qiáng)的代碼。它還可以用來編寫反常的和極其難以理解的代碼。顯然,后者在與安全相關(guān)的系統(tǒng)中是不可接受的。
其次,C++的語法是相對(duì)容易犯輸入錯(cuò)誤,從而導(dǎo)致完全有效的代碼。例如,鍵入“=”(賦值)而不是“==”(邏輯比較)太容易了,結(jié)果幾乎總是有效的(但錯(cuò)誤的),而在if語句的末尾加上一個(gè)額外的分號(hào)可以完全改變代碼的邏輯。
最后,C++的哲學(xué)是假設(shè)開發(fā)者知道他們正在做什么,這可能意味著如果出現(xiàn)錯(cuò)誤,編譯器允許開發(fā)者不注意這些錯(cuò)誤而通過編譯。在這方面,C++特別弱(盡管比C好)的一個(gè)領(lǐng)域是“類型檢查”。C++不會(huì)反對(duì)程序員嘗試在一個(gè)bool類型中存儲(chǔ)一個(gè)浮點(diǎn)數(shù)。大多數(shù)這樣的不匹配只是被迫變得兼容。如果 C++ 有一個(gè)方形釘和一個(gè)圓孔,它不會(huì)抱怨,而是讓它們適合!
示例:
規(guī)則:M6-2-1: (強(qiáng)制性,實(shí)施,自動(dòng)化)賦值運(yùn)算符不得用于子表達(dá)式
x = y;
x = y = z; // 不合規(guī)
if ( x != 0 ) // 合規(guī)
{ foo ( );
}
bool b1 = x != y; // 合規(guī)
bool b2;
b2 = x != y; // 合規(guī)
if ( ( x = y ) != 0 ) // 不合規(guī)
{ foo ( );
}
if ( x = y ) // 不合規(guī)
{ foo ( );
}
if ( int16_t i = foo ( ) ) // 合規(guī)
{
}
- 開發(fā)者對(duì)C++的誤解:
開發(fā)人員可能會(huì)誤解一種語言中構(gòu)造的效果。有些語言比其他語言更容易產(chǎn)生這種誤解。C語言++語言有許多領(lǐng)域容易出現(xiàn)開發(fā)人員引入的錯(cuò)誤。例如,操作符優(yōu)先級(jí)的規(guī)則定義良好,但很復(fù)雜,而且開發(fā)人員很容易在表達(dá)式中做出不正確的假設(shè)。
示例:
M5-0-2: 建議,實(shí)施,部分自動(dòng)化)表達(dá)式中的 C++ 運(yùn)算符優(yōu)先規(guī)則應(yīng)受到有限的依賴。
//何時(shí)強(qiáng)制性括號(hào)
賦值運(yùn)算符的右側(cè)操作數(shù)不強(qiáng)制性括號(hào),除非右側(cè)本身包含賦值表達(dá)式:
x = a + b; // 可以接受的
x = (a + b); // () 是不需要的
一元運(yùn)算符的操作數(shù)不強(qiáng)制性括號(hào):
x = a * -1; // 可以接受的
x = a * (-1); // () 不需要
否則,二元和三元運(yùn)算符的操作數(shù)應(yīng)為強(qiáng)制轉(zhuǎn)換表達(dá)式(參見 ISO/IEC 14882:2003 [1] 的第 5.4(2) 節(jié)),除非表達(dá)式中的所有運(yùn)算符都相同
x = a + b + c; // 可以接受, 但是考慮需求,對(duì)于a+b,不強(qiáng)制性括號(hào)
x = f ( a + b, c );
x = ( a == b ) ? a : ( a – b );
if ( a && b && c ) // 可以接受的
x = ( a + b ) – ( c + d );
x = ( a * 3 ) + c + d;
x = static_cast< uint16_t > ( a ) + b; // 不需要用來轉(zhuǎn)換
- 編譯器不執(zhí)行開發(fā)人員所期望的操作:
如果一種語言的特性沒有完全定義,或者不明確,那么開發(fā)人員可以對(duì)構(gòu)造的含義做一個(gè)假設(shè),而編譯器對(duì)它的解釋可能完全不同。C語言++語言中有許多領(lǐng)域沒有被完全定義,因此不同編譯器的行為可能因人而異。在某些情況下,行為甚至在單個(gè)編譯器中也會(huì)有所不同,這取決于上下文。ISO/IEC14882:2003[1]包含了許多可能以這種方式有所不同的問題。然而,它并沒有像C標(biāo)準(zhǔn)在其“可移植性問題”附件中那樣列出它們。(MISRA C++:2008的附錄B詳細(xì)了列出了C++漏洞)
示例:
規(guī)則 M4-5-3: (強(qiáng)制性,實(shí)施,自動(dòng)化)類型(普通)char 和 wchar_t 的表達(dá)式不得用作除賦值運(yùn)算符 =、相等運(yùn)算符 == 和 ! 之外的內(nèi)置運(yùn)算符的操作數(shù) = 和一元 & 運(yùn)算符。
根本原因:對(duì)字符數(shù)據(jù)的處理可能會(huì)產(chǎn)生與開發(fā)人員期望相反的結(jié)果。 例如,ISO/IEC 14882:2003 [1] §2.2(3) 僅要求數(shù)字“0”到“9”具有連續(xù)的數(shù)值。
例外:在特殊情況下,如果遵守相關(guān)限制,則可以使用以下運(yùn)算符:
二進(jìn)制 + 運(yùn)算符可用于將 0 到 9 范圍內(nèi)的整數(shù)值添加到“0”;
二元-運(yùn)算符可用于減去字符“0”;
關(guān)系運(yùn)算符 <、<=、>、>= 可用于確定字符(或?qū)捵址┦欠癖硎緮?shù)字
char_t ch = ‘t’; // 合規(guī)
uint8_t v;
if ( ( ch >= ‘a(chǎn)’ ) && ( ch <= ‘z’ ) ) // 不合規(guī)
{
}
if ( ( ch >= ‘0’ ) && ( ch <= ‘9’ ) ) // 符合例外
{
v = ch – ‘0’; // 符合例外
v = ch – ‘1’; // 不合規(guī)
}
else
{
// ...
}
ch = ‘0’ + v; // 符合例外
ch = ‘A’ + v; // 不合規(guī)
-
編譯器包含的錯(cuò)誤:
一個(gè)語言編譯器(以及相關(guān)的鏈接器等)。它本身就是一個(gè)軟件工具。編譯器可能并不總是能正確地編譯代碼。例如,在某些情況下,它們可能不符合語言標(biāo)準(zhǔn),或者它們可能只是包含“bug”。
因?yàn)镃語言++語言的某些方面很難理解,所以人們已經(jīng)知道編譯器編寫者會(huì)誤解該標(biāo)準(zhǔn)并錯(cuò)誤地實(shí)現(xiàn)它。該語言的某些領(lǐng)域比其他領(lǐng)域更容易發(fā)生這種情況。此外,編譯器的作者有時(shí)會(huì)有意識(shí)地選擇改變標(biāo)準(zhǔn)。
示例:
規(guī)則 M1-0-2: (強(qiáng)制性,工具鏈,非自動(dòng)化)僅當(dāng)多個(gè)編譯器具有通用的定義接口時(shí),才應(yīng)使用多個(gè)編譯器。
根本原因:多“編譯器”(任何工具) 包括:
混合語言、不同編譯器、同一編譯器的不同版本、同一編譯器的不同配置。
如果一個(gè)模塊要用C++以外的語言實(shí)現(xiàn),或者使用不同的編譯器編譯,需確保這個(gè)模塊的正確集成。強(qiáng)制性考慮的問題包括:堆棧使用、參數(shù)傳遞、數(shù)據(jù)值的存儲(chǔ)方式(長(zhǎng)度、對(duì)齊、混疊、疊加等)。 -
運(yùn)行時(shí)的錯(cuò)誤:
對(duì)于編譯正確的代碼,會(huì)出現(xiàn)一些不同的語言問題,但由于提供給它的特定數(shù)據(jù),代碼會(huì)在執(zhí)行過程中導(dǎo)致錯(cuò)誤。語言可以在可執(zhí)行代碼中構(gòu)建運(yùn)行時(shí)檢查,以檢測(cè)許多此類錯(cuò)誤并采取適當(dāng)?shù)拇胧?C++ 在提供運(yùn)行時(shí)檢查方面通常很差。這就是為什么由C++生成的代碼往往很小且高效的原因之一,但在執(zhí)行過程中檢測(cè)錯(cuò)誤時(shí)需要付出代價(jià)。C++編譯器通常不為諸如算術(shù)異常(例如除以零)、溢出、指針地址的有效性或數(shù)組綁定錯(cuò)誤等常見問題提供運(yùn)行時(shí)檢查。
示例:
規(guī)則 A18-0-2: (強(qiáng)制性,實(shí)施,自動(dòng)化)應(yīng)檢查從字符串到數(shù)值的轉(zhuǎn)換的錯(cuò)誤狀態(tài)。文章來源:http://www.zghlxwxcb.cn/news/detail-441372.html
std::uint16_t ReadFromStdin1() // 不合規(guī)
{
std::uint16_t a;
std::cin >> a; // 沒有檢測(cè)到錯(cuò)誤
return a;
}
std::uint16_t ReadFromStdin2() // 合規(guī)
{
std::uint16_t a;
std::cin.clear(); // 清除所有標(biāo)志位
std::cin >> a;
if (std::cin.fail())
{
throw std::runtime_error{"unable to read an integer"};
}
std::cin.clear(); // 為后續(xù)操作清除所有標(biāo)志位
return a;
}
三 總結(jié)
C++以其極高的編程效率在嵌入式系統(tǒng)開發(fā)中大放異彩,汽車嵌入式軟件開發(fā)出高效安全的軟件,需要嚴(yán)格的規(guī)范來對(duì)原生的C++標(biāo)準(zhǔn)進(jìn)行約束。關(guān)注AUTOSAR C++的規(guī)則更新是智能汽車軟件開發(fā)人員工程軟件開發(fā)技能成熟的標(biāo)志。文章來源地址http://www.zghlxwxcb.cn/news/detail-441372.html
到了這里,關(guān)于第七十七篇:車輛安全-車載軟件C++語言開發(fā)指南(AUTOSAR C++)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!