由于嵌入式系統(tǒng)行業(yè)的快速發(fā)展,嵌入式設(shè)備的代碼質(zhì)量成為首要關(guān)注的問(wèn)題之一。考慮到嵌入式系統(tǒng)開(kāi)發(fā)的特殊性(調(diào)試?yán)щy、出錯(cuò)成本高等),開(kāi)發(fā)人員需要使用專門(mén)的工具來(lái)提升自己的代碼質(zhì)量。
靜態(tài)代碼分析器就是這些工具之一。本文描述了靜態(tài)分析以及它如何在嵌入式系統(tǒng)中受益。
靜態(tài)代碼分析
首先,讓我們弄清楚靜態(tài)代碼分析器是什么以及它們可以執(zhí)行哪些功能。
靜態(tài)代碼分析器是分析程序而不實(shí)際執(zhí)行它的軟件。靜態(tài)分析工具比編譯器對(duì)源代碼進(jìn)行更深入的檢查。通常,編譯器只發(fā)現(xiàn)語(yǔ)法錯(cuò)誤。
靜態(tài)分析工具的工作原理:
分析器的輸入數(shù)據(jù)是源代碼(最好是可編譯的)
分析器將源代碼轉(zhuǎn)換為特殊模型以供進(jìn)一步分析(AST、語(yǔ)義模型等);
分析器通過(guò)對(duì)模型應(yīng)用一組診斷規(guī)則來(lái)搜索缺陷。診斷規(guī)則基于各種方法;
分析儀以方便您的格式保存所有發(fā)出的警告;
開(kāi)發(fā)人員只需要研究報(bào)告并修復(fù)所有缺陷;
利潤(rùn)!
靜態(tài)分析儀可以執(zhí)行廣泛的任務(wù)。讓我們介紹分析器最常見(jiàn)的任務(wù):
程序代碼中的錯(cuò)誤檢測(cè)。在這種情況下,靜態(tài)分析極大地補(bǔ)充了代碼審查。它允許您在您和您的同事開(kāi)始繁瑣的代碼審查之前發(fā)現(xiàn)并解決許多問(wèn)題;
廣義上的代碼質(zhì)量增強(qiáng)。代碼質(zhì)量可以包括可讀性、可維護(hù)性、代碼復(fù)雜性、內(nèi)聚程度以及可以直接或間接影響錯(cuò)誤數(shù)量的其他方面。因此,靜態(tài)分析器有助于遵循編碼標(biāo)準(zhǔn)(在公司內(nèi)接受并普遍接受);
代碼分析作為 CI/CD 中質(zhì)量門(mén)機(jī)制的一部分。分析器不僅可以警告代碼中的潛在錯(cuò)誤,還可以作為一種保護(hù)機(jī)制。如果代碼質(zhì)量水平不符合規(guī)定的要求,他們就會(huì)停止持續(xù)交付。如果檢測(cè)到錯(cuò)誤或不符合標(biāo)準(zhǔn)的代碼片段,此類代碼分析器會(huì)擴(kuò)展編譯器行為并阻止構(gòu)建;
項(xiàng)目指標(biāo)的收集、統(tǒng)計(jì)數(shù)據(jù)的收集、反映項(xiàng)目“總體健康狀況”的圖形和圖表結(jié)構(gòu)。
實(shí)施效益
靜態(tài)分析器已被證明對(duì)嵌入式軟件非常有用。讓我們看看靜態(tài)分析最明顯的積極方面。
首先,靜態(tài)分析的使用減少了昂貴的(如果不是不可能的話)已經(jīng)發(fā)布的設(shè)備“閃爍”的可能性。
嵌入式系統(tǒng)軟件中的錯(cuò)誤非常麻煩。問(wèn)題是一旦開(kāi)始大規(guī)模生產(chǎn),這些錯(cuò)誤就不可能或幾乎不可能糾正。假設(shè)一家公司已經(jīng)生產(chǎn)了數(shù)千臺(tái)洗衣機(jī)并將其交付給商店。但是,結(jié)果機(jī)器在某種模式下無(wú)法正常工作。公司應(yīng)該怎么做?一般來(lái)說(shuō),這個(gè)問(wèn)題是修辭性的,有兩種實(shí)際選擇:
順其自然,在各個(gè)網(wǎng)站上收到負(fù)面的客戶反饋,破壞聲譽(yù)。當(dāng)然,公司可以發(fā)布并發(fā)送手動(dòng)添加說(shuō)“不要這樣做”。然而,這是一個(gè)“弱”的選擇;
退出銷(xiāo)售機(jī)器并開(kāi)始更新固件。這是一個(gè)昂貴的選擇。
發(fā)布多少設(shè)備并不重要。修復(fù)錯(cuò)誤可能有問(wèn)題,甚至為時(shí)已晚。火箭墜毀——錯(cuò)誤被發(fā)現(xiàn),但為時(shí)已晚。患者死亡——錯(cuò)誤被檢測(cè)到,但它不會(huì)讓人們回來(lái)。導(dǎo)彈防御系統(tǒng)的目標(biāo)精度損失- 檢測(cè)到錯(cuò)誤,但損壞已經(jīng)造成。汽車(chē)休息不起作用- 檢測(cè)到錯(cuò)誤,但這無(wú)助于車(chē)禍?zhǔn)芎φ摺3绦蝈e(cuò)誤的代價(jià)是可怕的,不是嗎?
結(jié)論很簡(jiǎn)單:嵌入式設(shè)備的代碼應(yīng)該盡可能徹底地測(cè)試。特別是如果錯(cuò)誤可能導(dǎo)致人員傷亡或巨大的經(jīng)濟(jì)損失。
靜態(tài)代碼分析是檢測(cè)錯(cuò)誤的過(guò)程,但它不保證會(huì)發(fā)現(xiàn)代碼中的所有錯(cuò)誤。但是,開(kāi)發(fā)人員應(yīng)該利用任何機(jī)會(huì)額外檢查代碼的正確性。靜態(tài)分析器可以指出即使在多次代碼審查之后仍然存在的各種錯(cuò)誤。
如果靜態(tài)分析可以幫助減少設(shè)備代碼中的錯(cuò)誤數(shù)量,那就太棒了。也許這些特殊錯(cuò)誤的發(fā)現(xiàn)將防止生命損失。或者,也許這些公司不會(huì)浪費(fèi)很多錢(qián),也不會(huì)因?yàn)榭蛻敉对V而失去良好的聲譽(yù)。
其次,靜態(tài)代碼分析器顯著降低了軟件測(cè)試和調(diào)試過(guò)程的成本。
靜態(tài)分析允許您在編碼期間或夜間構(gòu)建期間發(fā)現(xiàn)錯(cuò)誤。結(jié)果,大多數(shù)錯(cuò)誤的搜索和修復(fù)可以便宜得多。
可能每個(gè)開(kāi)發(fā)人員都嘗試過(guò)“刷新”設(shè)備,但沒(méi)有成功。例如,在此過(guò)程中,設(shè)備沒(méi)有設(shè)置正確的電壓或完全燒壞。發(fā)生了什么,您在哪里尋找問(wèn)題?畢竟,不僅僅是軟件錯(cuò)誤可能是問(wèn)題的根源。也可能是硬件本身的錯(cuò)誤或質(zhì)量差的布局。因此,發(fā)現(xiàn)錯(cuò)誤的過(guò)程可能需要很長(zhǎng)時(shí)間。
最悲傷的場(chǎng)景:
開(kāi)發(fā)人員 100% 確定他編寫(xiě)的代碼是正確的;
電路工程師和其他負(fù)責(zé)硬件的同事參與了該項(xiàng)目;
尋找問(wèn)題的過(guò)程緩慢而費(fèi)力;
開(kāi)發(fā)人員再次查看代碼并突然發(fā)現(xiàn) - 一個(gè)錯(cuò)字;
超級(jí)低效浪費(fèi)隊(duì)友的精力和時(shí)間;
這很尷尬和不愉快。
由于以下原因,可能會(huì)彈出此類錯(cuò)誤。在正在進(jìn)行的項(xiàng)目中,開(kāi)發(fā)人員使用了他的舊做法,他需要至少適應(yīng)項(xiàng)目。例如,他可以編寫(xiě)以下代碼片段:
uchar Arr[3];
。..。
for (uchar idx = 0; idx != 4; idx++)
avg += Arr[idx];
avg /= 3;
這個(gè)錯(cuò)誤的背景如下。開(kāi)發(fā)人員以他之前的開(kāi)發(fā)為基礎(chǔ),代碼主要是使用復(fù)制粘貼方法編寫(xiě)的。他沒(méi)注意,忘了把4換成3在一行。結(jié)果,他在訪問(wèn)位于數(shù)組邊界之外的索引時(shí)出現(xiàn)了未定義的行為。這樣的代碼可能是陰險(xiǎn)的。程序在調(diào)試過(guò)程中可以正常工作。但是,在實(shí)際情況下,當(dāng)客戶端多次運(yùn)行它時(shí),它可能會(huì)崩潰。如果靜態(tài)分析器發(fā)現(xiàn)這樣的錯(cuò)誤,那就太好了。
因此,為避免調(diào)試過(guò)程曲折而費(fèi)力,在刷機(jī)之前盡可能多地檢測(cè)出缺陷位置非常重要。
第三,靜態(tài)分析的使用保證了沒(méi)有太多經(jīng)驗(yàn)的開(kāi)發(fā)人員。
程序錯(cuò)誤可以形象地分為兩種類型。開(kāi)發(fā)人員知道第一種類型的錯(cuò)誤。由于疏忽,這些錯(cuò)誤意外地出現(xiàn)在代碼中。第二種錯(cuò)誤出現(xiàn)在開(kāi)發(fā)人員根本不知道不可能以這種方式編寫(xiě)代碼的情況下。換句話說(shuō),他們可以隨心所欲地查看此類代碼,但仍然不會(huì)發(fā)現(xiàn)錯(cuò)誤。
靜態(tài)分析器包含有關(guān)各種代碼模式的知識(shí)庫(kù)。在某些情況下,這些模式會(huì)導(dǎo)致錯(cuò)誤。因此,他們可以指出開(kāi)發(fā)人員自己不會(huì)發(fā)現(xiàn)的錯(cuò)誤。一個(gè)例子是使用 32 位 time_t 類型,這可能會(huì)導(dǎo)致設(shè)備在2038之后無(wú)法正常工作。
另一個(gè)例子是程序的未定義行為,這是由于不當(dāng)使用移位運(yùn)算符《《/》》而發(fā)生的。這些運(yùn)算符在微控制器的代碼中被廣泛使用。不幸的是,開(kāi)發(fā)人員經(jīng)常非常粗心地使用這些運(yùn)算符。這使得程序不可靠并且依賴于編譯器的特定版本和設(shè)置。同時(shí),程序可以運(yùn)行,但這不是因?yàn)樗拇a寫(xiě)得對(duì),而是因?yàn)?a target="_blank">開(kāi)發(fā)者很幸運(yùn)。
使用靜態(tài)分析器,開(kāi)發(fā)人員可以對(duì)沖許多此類不愉快的情況。此外,您可以使用分析器來(lái)控制整體代碼質(zhì)量。當(dāng)項(xiàng)目的團(tuán)隊(duì)正在成長(zhǎng)或變化時(shí),這一點(diǎn)很重要。換句話說(shuō),分析器有助于跟蹤初學(xué)者是否開(kāi)始編寫(xiě)糟糕的代碼。
第四,現(xiàn)代靜態(tài)分析器不僅能發(fā)現(xiàn)代碼錯(cuò)誤和漏洞,還支持嵌入式系統(tǒng)的編碼標(biāo)準(zhǔn)。這些標(biāo)準(zhǔn)提高了程序的安全性、可移植性和可靠性水平。
C 和 C++ 被稱為嵌入式系統(tǒng)的流行編程語(yǔ)言。MISRA C、MISRA C++ 和 AUTOSAR C++ 等標(biāo)準(zhǔn)是為這些語(yǔ)言開(kāi)發(fā)的。每個(gè)標(biāo)準(zhǔn)都有相當(dāng)多的規(guī)則和建議(MISRA C:143,MISRA C++:228,AUTOSAR C++:超過(guò) 350)。在沒(méi)有靜態(tài)代碼分析器的情況下編碼時(shí),根本不可能遵守這么多的規(guī)則和建議。這些規(guī)則是開(kāi)發(fā)人員需要避免的編碼模式,從而減少出錯(cuò)的可能性。目前,所有主要的靜態(tài)分析參與者(Coverity、Klockwork、PVS-Studio,。..)都在努力盡可能地增加標(biāo)準(zhǔn)的覆蓋范圍。
編碼標(biāo)準(zhǔn)
MISRA 的歷史始于很久以前。回到 90 年代初,“安全 IT”英國(guó)政府計(jì)劃為各種與電子系統(tǒng)安全相關(guān)的項(xiàng)目提供資金。MISRA(汽車(chē)工業(yè)軟件可靠性協(xié)會(huì))項(xiàng)目本身的成立是為了創(chuàng)建用于開(kāi)發(fā)陸地車(chē)輛微控制器軟件的指南 - 主要是汽車(chē)。
MISRA(作為一個(gè)組織)是一個(gè)由來(lái)自各種汽車(chē)和飛機(jī)行業(yè)的利益相關(guān)者組成的社區(qū)。
賓利汽車(chē);
福特汽車(chē)公司;
捷豹路虎;
德?tīng)柛2裼拖到y(tǒng);
堀場(chǎng)米拉;
千變?nèi)f化電氣;
偉世通工程服務(wù);
利茲大學(xué);
英國(guó)里卡多;
采埃孚天合。
非常強(qiáng)大的市場(chǎng)參與者,不是嗎?毫不奇怪,他們的第一個(gè)與語(yǔ)言相關(guān)的標(biāo)準(zhǔn) MISRA C 在關(guān)鍵嵌入式系統(tǒng)的開(kāi)發(fā)人員中獲得了廣泛的認(rèn)可。不久之后,出現(xiàn)了 MISRA C++。逐漸地,標(biāo)準(zhǔn)的版本已經(jīng)更新和修訂,以涵蓋語(yǔ)言的新功能。目前,當(dāng)前版本是 MISRA C: 2012 和 MISRA C++: 2008。
MISRA 最顯著的特點(diǎn)是其對(duì)細(xì)節(jié)的難以置信的關(guān)注和在確保安全和安保方面的極度細(xì)致。作者不僅將所有 C 和 C++ 缺陷集中在一個(gè)地方(例如 CERT 的作者)。他們還仔細(xì)制定了這些語(yǔ)言的國(guó)際標(biāo)準(zhǔn),并寫(xiě)出了所有可能出錯(cuò)的方法。之后,他們添加了關(guān)于代碼可讀性的規(guī)則和建議。畢竟,在簡(jiǎn)單易讀的代碼中更難出錯(cuò),在 Code-Review 期間更容易發(fā)現(xiàn)錯(cuò)誤。
通常,第一次遇到 MISRA 的人會(huì)覺(jué)得該標(biāo)準(zhǔn)的目的是“禁止這個(gè)和禁止那個(gè)”。事實(shí)上,確實(shí)如此,但只是部分如此。
該標(biāo)準(zhǔn)確實(shí)有許多禁止某些行為的規(guī)則。但是,這并不是要全面禁止,而是要列出所有可能導(dǎo)致安全漏洞的方式。對(duì)于大多數(shù)規(guī)則,您自己選擇是否需要遵守它們。讓我更詳細(xì)地解釋一下。
MISRA C 規(guī)則分為三個(gè)主要類別:強(qiáng)制、必需和建議。在任何情況下都不得違反強(qiáng)制性規(guī)則。例如,本節(jié)包括規(guī)則:“不要使用未啟動(dòng)變量的值”。所需的規(guī)則不那么嚴(yán)格。它們?cè)试S偏差的可能性。但是開(kāi)發(fā)人員需要以書(shū)面形式證明這些偏差的合理性并詳細(xì)記錄它們。其余規(guī)則屬于咨詢類別——它們是非強(qiáng)制性的。
MISRA C++ 有點(diǎn)不同:沒(méi)有 Mandatory 類別,大部分規(guī)則屬于Required 類別。因此,事實(shí)上,您有權(quán)違反任何規(guī)則——只是不要忘記記錄偏差。還有文檔類別。它包括與一般實(shí)踐相關(guān)的強(qiáng)制性規(guī)則(不允許有偏差),例如“必須記錄匯編程序的每次使用”或“包含的庫(kù)必須符合 MISRA C++”。
該標(biāo)準(zhǔn)既包含對(duì)問(wèn)題問(wèn)題的描述,也包含在承擔(dān)某項(xiàng)任務(wù)之前必須了解的提示:如何根據(jù) MISRA 設(shè)置開(kāi)發(fā)流程;如何使用靜態(tài)分析器檢查代碼的合規(guī)性;一個(gè)人必須維護(hù)哪些文件,如何填寫(xiě)它們等等。
目前,MISRA 不斷發(fā)展。例如,MISRA 在 2019 年初發(fā)布了《MISRA C:2012 第三版(第一次修訂)》。這是 MISRA C:2012 版更新和擴(kuò)展了新規(guī)則。同時(shí),即將發(fā)布的《MISRA C: 2012 Amendment 2 – C11 Core”公布,這是 2012 年的修訂標(biāo)準(zhǔn)。
MISRA C++ 也不會(huì)停滯不前。如您所知,MISRA C++ 的最后一個(gè)標(biāo)準(zhǔn)可以追溯到 2008 年,因此它所涵蓋的語(yǔ)言的最新版本是 C++03。正因?yàn)槿绱耍€有一個(gè)類似于MISRA的標(biāo)準(zhǔn),它的名字叫AUTOSAR C++。它最初旨在作為 MISRA C++ 的延續(xù),并旨在涵蓋該語(yǔ)言的更高版本。與其策劃者不同,AUTOSAR C++ 每年更新兩次,目前支持 C++14。新的 C++17 和 C++20 更新尚未到來(lái)。
結(jié)論
在本文中,我想說(shuō)明使用靜態(tài)分析器對(duì)任何嵌入式項(xiàng)目都絕對(duì)有用。使用靜態(tài)分析將幫助您:
減少查找和修復(fù)錯(cuò)誤所需的時(shí)間;
減少嚴(yán)重錯(cuò)誤的可能性;
減少對(duì)固件更新的需求;
監(jiān)控整體代碼質(zhì)量;
監(jiān)控新團(tuán)隊(duì)成員的表現(xiàn);
嚴(yán)格遵守一定的軟件開(kāi)發(fā)標(biāo)準(zhǔn);
監(jiān)控第三方模塊/庫(kù)的代碼質(zhì)量。
審核編輯:郭婷
-
嵌入式
+關(guān)注
關(guān)注
5082文章
19111瀏覽量
304882 -
C++
+關(guān)注
關(guān)注
22文章
2108瀏覽量
73628 -
代碼
+關(guān)注
關(guān)注
30文章
4780瀏覽量
68539
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論