C++在嵌入式應用中的安全問題

     在嵌入式系統的軟件設計中,“彙編語言+C語言”早已成爲理所當然的經典組合。的確,對於硬件配置來說,彙編語言清晰明瞭;對於上層設計來說,C語言緊湊高效。這樣的搭配能夠滿足大多數傳統嵌入式系統應用的需要。隨着技術水平的提高,今天的嵌入式系統也比過去更加深入到人們的日常生活中,大到汽車、飛機、火箭,小到手機、打印機、鬧鐘、手錶,都可以找到嵌入式系統的蹤影。然而,這看似一成不變的情況,也在悄然轉變。隨着網絡、多媒體等技術的出現、發展與普及,對嵌入式系統應用有了新的要求,也給了其他高級語言,特別是C++語言以機會。

  由此帶來的在語言使用中的安全問題,目前雖然還未凸顯,但根據以往的經驗來看,終將成爲限制行業發展的新瓶頸。已有的C++語言國際標準雖然龐大細緻,但作爲一個“語言標準”,只能是盡力做得面面俱到,其目標在於構造一個語句合法性的權威依據,以約束人們對於C++的使用。但它並不是針對應用而寫的規範,對於可能遇到的安全性問題也無法進行特別深入的探討,更加沒有安全方面的實踐經驗支撐。一個針對安全方面的、被國際所認可的使用規範,無疑是C++語言在嵌入式系統中得到廣泛應用的堅實基礎與助推劑。

  1 C++在嵌入式應用中的機遇與挑戰

  C++作爲一門高級語言,人們在提及它時,總難免會談到C語言。直至今天,很多人對於C++語言的認識依然是“C語言的超集”。這是因爲C++的起源與C語言有着千絲萬縷的聯繫。

  1978年,美國貝爾實驗室的Dennis Ritchie和BrianKernighan在BCPL以及其簡化版本B語言的基礎之上開發了C語言,併合作出版了《The C Programming Lan-guage》。C語言迅速得到了大家的認可,並廣爲流傳。1989年,ANSI推出了第一個C語言的標準——X3.159-1989,並被ISO採納,隨之發佈。ISO/IEC 9899-1990。早在C語言標準發佈之前,貝爾實驗室的Bjarne Stroustrup就致力於在C語言裏增加類、函數類型檢查以及其他的一些優秀特徵,於1980年發佈“C with Classes”。經過持續的努力,他最終完成了對C語言的改造,由此創生出一門新語言——C++,並出版了《The C++ ProgrammingLanguage》一書。由於它帶來了持續的影響,ISO於1998年發佈ISO/IEC 14882:1998;幾乎同一時間,ANSI也發佈了類似標準,這標誌着C++作爲一門獨立語言的標準化得到了官方的認可。

  統計數據表明,日常生活中一個美國人平均佔用8個微控制器,這些都離不開嵌入式系統的應用。然而嵌入式系統軟件技術似乎落後於當前的軟件發展形勢,近年來才逐漸由彙編語言過渡到面向過程的C語言。但對於面嚮對象語言的應用還很有限。

  這一方面是由於嵌入式開發人員多年來應付有限資源的經驗而養成的保守態度,另一方面也是由於長久以來,嵌入式系統應用設計中,人們要花費許多精力在底層硬件的驅動上,功能實現也主要侷限在實時操作系統和相關支撐軟件的層次,並不涉及過多的應用軟件開發。這種在嚴苛條件下追求效率與實時性的任務,其他的高級語言並沒有特別的優勢。

  最近幾年,嵌入式系統領域又有了新的發展。首先,隨着手機、PDA等消費性電子產品的飛速增長,嵌入式系統的市場規模在迅速擴大,同時越來越多的智能嵌入式應用場合需要互聯網的支持,這要求嵌入式系統的軟件具有更好的應用性和更高的複雜性;其次,隨着芯片等相關領域的技術進步,嵌入式系統工程師們不再需要時時刻刻去考慮資源是否夠用了。當面向對象的高級語言參與到嵌入式系統設計中去不再遙不可及時,語言的效率則成爲突出的問題。根據《Thinking in C++》一書的總結,C++與C的效率差別往往在±5%,這使得C++在新一輪的嵌入式應用發展浪潮中佔得先機。

  值得注意的是,儘管自1998年發佈最初的C++標準——ISO/IEC 14882:1998以來,每5年都會對此標準進行一次更新,但是由於C++語言過於複雜,以及它經歷了長年的演變,直到2004年,沒有任何一款編譯器完全支持ISO C++。這對於時常要面對各種嚴苛條件的嵌入式系統應用工程師們來說,是難以忍受的。同時,即使是符合ISO C++標準的語句或者格式,對於實際的應用場合來說,也存在着重大隱患,而不應當被直接採用。因此,人們迫切需要一個正式的基於安全角度考慮的C++語言使用規範。

  2 關於MISRA

  MISRA(the Motor Industry Software Reliability As-sociation),即汽車工業軟件可靠性協會,於1994.年在英國成立,以“協助汽車工業提供安全、可靠的軟件”爲使命,期望通過“規範指南”的形式來約束人們在汽車電子以及其他嵌入式系統開發領域或涉及安全與可靠性的領域中對於程序語言的使用。由於這些“規範指南”都是從大量工程實踐中總結的第一手經驗,因而具有極高的指導意義。

  經過4年準備,它在1998年發佈了一個針對汽車工業的《Guidelines for the Use of the C Langtlage in VehicleBased Software》,簡稱“MISRA C:1998\'’,針對那些滿足C語言標準,卻存在安全隱患的語言使用習慣,提出了127條規則。由於它很好地解決了C語言國際標準的冗繁性,以及其中對於安全性考慮的不足性,從而得到了廣泛的好評。MISRA-C不僅成爲衆多汽車廠商推崇的行業標準,其影響力更是遠遠超出了汽車工業,得到鐵路、航空航天、國防、醫療等衆多領域的認可,成爲“最佳實踐”解決方案。2004年,MISRA對於已有的規則進行改編與擴充,推出了“MISRA C 2004”,首次將該規範指南的對象從汽車工業推廣到所有具有安全性要求的系統應用中去,包含了強制規則121條,推薦規則20條,並刪除了15條舊規則,共計含有141條規則。

  時至今日,MISRA組織不僅是汽車工業軟件規範的權威,其制定的規範指南更得到了嵌入式系統應用領域的廣泛認可。考慮到近年來,C++語言在嵌入式系統中的應用越來越多,2005年MISRA C++委員會成立,並於2008年推出針對C++語言的《MISRA C++:2008——Guidelines for the USe of the C++ language in critical sys-tems>>,以下簡稱“MISRA C++:2008”。有興趣的讀者可以聯繫相關網站:http://www.misra-cpp.com/,購買詳細的文檔。

  MISRA C++:2008同樣從推出之日起,就得到了業內外廣泛關注。例如:LDRA軟件公司一直跟蹤着MIS-RA C++:2008的制定進展,在MISRA C++:2008發佈時同步宣稱已經完成了對工具套件產品的相應改進,使其符合MISRA C++:2008標準。(LDRA的Testbed產品曾成功用於“神舟”飛船項目的軟件測試)

 3 MISRA C++概述

  作爲規範指南,MISRA C++:2008基於ISO/IEC 14882:2003的C++語言國際標準,以規則(rule)的形式,給出了相關的建議。它的規則又細分爲以下3種類型:

  ①強制型(required),必須符合、允許例外;

  ②推薦型(advisory),推薦符合;

  ③不容討論型(document),必須符合、不許例外。

  MISRA C++:2008中共給出了20個大類的規則(編號並不連續),細分爲228條。詳細情況如表1所列。



  文檔中所有規則的書寫格式如下:



  每條規則之後都有詳細的解釋,並給出了一些具體的程序語句作爲例子。下面分別針對上述3種規則類別,進行舉例說明。

  規則0-1-1(強制)工程中不允許包含無法觸及的代碼



  上述例子裏,條件判斷中的賦值語句和return語句之後的自增語句都是在任何條件下都無法觸及的死代碼,不允許這樣使用。

  規則0-1-2 (強制) 工程中不允許含有永遠不會被執行的路徑

  enum ec{RED,BLUE,GREEN)col;

  if(col<=GREEN) //不符合規則,條件永遠爲真

  {

  //Will always get,here

  }

  else

  {

  //代碼永遠不會到達這裏

  }

  由於枚舉類型有默認的初始賦值0,1,2,…,故col永遠≤GREEN。上述例子中,含有任何條件下都不會被執行的路徑,不允許這樣使用。

  規則5-2-10(推薦) 自增(++)/自減(--)運算符不應與表達式中其他運算符混合使用諸如下面的例程將導致理解上的混淆以及結果的不確定,在程序設計時應儘可能避免。

  u8a=++u8b+u8c-; //不符合規則

  規則0-4-2 (不容討論) 對於浮點運算(floating-point)算法的使用,必須給出記錄

  安全的使用浮點算法需要具有較高的數字分析技能和對編譯器及硬件對象的深入瞭解。因此在使用浮點算法時,必須先進行分析:是否必須使用它、採取的方法是否可行、過程是否得到了正確的執行,並將上述結果做出記錄。

  規則16-6-1 (不容討論) 所有的庫函數代碼必須符合MISRA C++

  上述這些例子只是爲了讓大家對MISRA C++:2008的3種規則有一定的認識,我們會結合相關內容,在接下來的幾篇文章中進一步討論學習。不難發現,許多違反了MISRA C++:2008中規則的例程都是符合C++語言標準的,但出於安全性考慮,應當被禁止或者謹慎使用。通覽之後,往往會發現自己平時從未注意的一些編程習慣,都已經被嚴令禁止。它們有些是明顯有礙安全性的,有些則相對隱蔽。

 

  然而MISRA的號召力是不容小覷的。以嵌入式實時操作系統μC/OS-II爲例,其2.52版本雖然已經於2000年通過了美國航空管理局(FAA)的安全認證,但2003年μC/OS-II的作者就根據MISRA C:1998規範又對源碼作了相應的修改,併發布了2.62的新版本,宣稱其源代碼99%符合MISRA C:1998的要求。

  4 安全性問題

  對於安全性,MISRA給出以下5種可能的安全問題來源:開發人員的錯誤、開發人員對於語言的誤解、編譯器沒有按照開發人員的預期工作、編譯器本身含有錯誤、運行錯誤。

  這些錯誤的來源與實際使用的是何種計算機語言沒有關係,可以說比較全面地包含了嵌入式系統開發以及其他相關的軟件設計中可能導致安全問題的所有渠道。

  作爲C++這樣一門面向對象的高級語言(由於其與C的淵源,嚴格地說,C++是具有某些面向對象特徵的過程語言),通過類、函數參數類型檢查、模版、異常處理以及派生、繼承、多態等手段,使得其在保有高效率的同時,實現了強大的功能,並帶來了自頂向下的模塊化程序設計理念。但編程靈活度的提高,也令其代碼複雜而易錯。與C語言相比,它所面對的安全問題將更爲隱蔽,更加難以發現。但就對數據的封裝而言,C++遠遠優於C,只要參照合理的規範指南,進行項目的開發,就可以通過充分發揮C++靈活的特點,應用到更多更廣的工程領域。

  5 行業展望

  標準與規範從來沒有如眼下這般備受重視過。一個權威的標準或規範,不僅將成爲相關領域的“金科玉律”,更是行業動向的風向標。可以說正是由於MISRA-C的存在,使得在高級語言種類繁多的今天,C語言的地位依然無可替代。

  此次MISRA攜着在C語言上的巨大成功,選擇了C++語言進行新的規範化嘗試,不僅因爲C++語言的羣衆基礎深厚,更是表明了嵌入式系統領域內大多數專家的觀點:如果說未來能有一門語言取代目前C語言在嵌入式系統應用中的地位的話,也只能是C++語言。一名成功的嵌入式系統工程師,必須是對行業動向極爲敏感的,也只有這樣,才能在知識爆炸的今天緊跟時代潮流。從使用C語言到使用C++語言是一個巨大的跨越,決不僅僅像使用“增強的C”那麼簡單,需要從現在就開始學習。而從學習之初就養成的良好的語言使用習慣,將決定將來進階的速度與可能性。MISRA C++:2008無疑是培養這樣良好習慣的最佳手冊。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章