为什么您应该使用基于标准的开发实践
為什么您應該使用基于標準的開發實踐
Why you should use standards-based development practices (even if you don’t have to)
整個行業圍繞著功能安全、安全和編碼標準(如IEC 61508、ISO 26262、IEC 62304、MISRA C和CWE)所倡導的驗證和驗證實踐而發展起來。當然,并不是每個人都有義務遵循這些標準所提倡的正式過程和方法,尤其是當他們的軟件不需要滿足這些標準的嚴格性時。但標準支持最佳實踐,因為經驗表明,它們代表了實現高質量、可靠和健壯軟件的最有效方法。
遵循這些標準的最佳實踐開發技術有助于確保首先不會在代碼中引入錯誤,從而減少對大量調試活動的需求,這些活動可能會減慢上市時間并增加成本。當然,并不是所有的開發者都有足夠的時間和預算用于航空航天、汽車或醫療器械行業。然而,他們所部署的技術代表了一個工具箱,對任何開發團隊都有巨大的潛在好處,無論關鍵性是否強制使用它們。
錯誤類型和解決錯誤的工具
在軟件中可以找到兩種關鍵類型的錯誤,并使用工具解決這些錯誤,以防止錯誤的引入:
編碼錯誤。一個例子是試圖訪問數組邊界之外的代碼。這類問題可以通過執行靜態分析來檢測。
應用程序錯誤。只有通過準確地知道應用程序應該做什么,這意味著根據需求進行測試,才能檢測到這些問題。
編碼錯誤和代碼復查
靜態分析是檢測代碼錯誤的一種有效技術,尤其是當它從項目開始部署時。一旦代碼被分析,就可以查看不同類型的結果。代碼評審是根據編碼標準(如misrac:2012)檢查代碼的地方,這是本文將重點討論的內容。
理想情況下,所有的嵌入式項目都應該使用像Ada這樣的安全語言。Ada包含許多特性來強制執行一個自然減少錯誤的思考過程(例如嚴格的輸入)。不幸的是,很難找到程序員艾達知識和經驗,所以大多數公司,而不是使用C和/或C++。然而,這些語言甚至給經驗豐富的開發人員帶來了隱患。幸運的是,通過執行代碼復查,可以避免大多數潛在的陷阱。
避免代碼中的缺陷的最好方法是避免將它們放在那里。這聽起來很明顯,但這正是編碼標準所做的。在C和C++世界中,大約80%的軟件缺陷是由錯誤使用大約20%的語言造成的。如果語言的使用受到限制,以避免語言中已知有問題的部分,那么缺陷就可以避免,軟件質量也會大大提高。
與C/C++編程語言有關的基本語言失敗的原因是未定義行為、實現定義行為和未指定行為。這些行為會導致軟件錯誤和安全問題。
作為實現定義行為的一個示例,考慮當有符號整數右移時高階位的傳播。結果是0x40000000還是0xc000000?
Figure 1: The behavior of some C and C++ constructs depends on the compiler used.
答案取決于您使用的編譯器(圖1)。可能是兩者之一。函數參數的求值順序在C語言中未指定。在圖2所示的代碼中,rollDice()函數只是從保存值“1、2、3和4”的循環緩沖區中讀取下一個值,預期返回值將是1234。但是,不能保證這一點,至少有一個編譯器將生成返回值3412的代碼。
Figure 2: The behavior of some C and C++ constructs is unspecified by the languages.
C/C++語言存在很多這樣的缺陷,但通過使用編碼標準,這些未定義的、未指定的和實現的行為可以被避免。類似地,使用goto或malloc之類的構造可能會導致缺陷,因此可以使用編碼標準來防止這些構造被使用。在混合有符號和無符號值時會出現許多問題,這在大多數情況下不會產生問題,但有時可能會出現有符號值溢出并變為負的情況。
編碼標準還可以檢查代碼是否以特定的樣式編寫;例如,驗證是否未使用制表符、縮進是否為特定大小或圓括號是否位于特定位置。這一點很重要,因為需要進行一些手動代碼檢查,并且當在不同的編輯器中查看代碼時,制表符的大小不同,那么奇怪的布局會分散審閱者的注意力,使其無法集中精力審閱代碼。
一些開發人員對編寫“聰明”的代碼感到內疚,這些代碼可能是高效和緊湊的,但也可能是神秘和復雜的,使其他人難以理解。最好保持它的簡單性,讓編譯器負責生成一個高效的二進制文件。再一次,使用編碼標準可以幫助防止開發人員創建未記錄的、過于復雜的代碼。
最著名的編程標準可能是MISRA標準,該標準于1998年首次為汽車行業發布。這些標準的流行反映在提供某種程度的MISRA檢查的嵌入式編譯器的數量上。MISRA的最新版本是MisraC:2012,它的頁數幾乎是前一版本的兩倍。這些附加文檔中的大多數都包含關于為什么每個規則存在的有用解釋,以及該規則的各種異常的詳細信息。MISRA有幾個指導原則,在適用的情況下,它們包含對標準或未定義、未指定和實現定義行為的引用。在圖3中可以看到一個例子。
Figure 3: MISRA C references to undefined, unspecified, and implementation-defined behavior.
大多數MISRA指南是“可判定的”,這意味著工具應該能夠識別是否存在違規行為。然而,有一些準則是“不可判定的”,這意味著工具并不總是能夠推斷出是否存在違規行為。例如,未初始化的變量作為輸出參數傳遞給應該初始化它的系統函數。但是,除非靜態分析可以訪問系統函數的源代碼,否則無法知道該函數在初始化變量之前是否使用了該變量。如果使用了一個簡單的MISRA檢查器,那么它可能不會報告這種違規行為,可能會導致假陰性。或者,如果MISRA檢查員不確定,那么它可以報告違規行為,可能導致誤報。什么是最好的?不知道可能有問題嗎?或者確切地知道在哪里花時間來確保絕對沒有問題?當然,最好是有假陽性而不是假陰性。
2016年4月,MISRA委員會發布了對MISRA C:2012的修正案,增加了14條指南,以幫助確保MISRA不僅適用于安全關鍵型軟件,而且適用于安全關鍵型軟件。其中一個指導方針是指令4.14,如圖4所示,它有助于防止由于未定義行為而導致的陷阱。
Figure 4: MISRA and security considerations.
應用程序錯誤和需求測試
只有通過測試產品做了它應該做的事情,這意味著有需求,才能發現應用程序錯誤。避免應用程序錯誤需要設計正確的產品和正確的設計產品。
設計正確的產品意味著預先建立需求,并確保需求和源代碼之間的雙向可追溯性,這樣每個需求都得到了實現,每個軟件功能都可以追溯到一個需求。任何缺失或不必要的功能(不滿足要求)也是應用程序錯誤。產品權利設計是確認開發的系統代碼滿足項目需求的過程,這可以通過執行基于需求的測試來實現。
圖5顯示了一個雙向跟蹤的示例。在這個簡單的例子中,選擇了一個單一的功能,并強調了從功能到低級需求,再到高級需求,最后到系統級需求的上游可追溯性。
Figure 5: Bidirectional traceability, with function selected.
在圖6中,選擇了一個高級需求,突出顯示了對系統級需求的上游可追溯性,以及對低級需求和源代碼功能的下游可追溯性。
Figure 6: Bidirectional traceability, with requirement selected.
這種可視化可追溯性的能力可以在生命周期的早期發現可追溯性問題(應用程序錯誤)。
測試代碼功能需要知道它應該做什么,這意味著有低級需求來說明每個函數的功能。圖7顯示了一個低級需求的示例,在本例中,它完整地描述了單個功能。
Figure 7: Example low-level requirement.
測試用例來自于低層次的需求,如表1所示。
表1:來自低級需求的測試用例。
使用單元測試工具,可以在主機或目標上執行這些測試用例,以確保代碼的行為符合需求。圖8顯示所有測試用例都已回歸并通過。
Figure 8: Performing unit tests.
當所有的測試都被測試時,確保所有的測試都已經被測試過了。如果覆蓋率不是100%,那么可能需要更多的測試用例,或者有多余的代碼需要刪除。
結論
隨著軟件復雜性的增加,潛在的軟件錯誤也會增加。最佳實踐開發技術有助于防止這些錯誤的發生。最佳實踐開發包括使用最先進的編碼標準,如MISRA C:2012,測量代碼的度量,跟蹤需求,并實現基于需求的測試。在沒有義務滿足標準的情況下,這些技術的應用程度顯然由開發團隊決定。然而,標準支持這些實踐,因為經驗表明,它們是實現高質量、可靠和健壯軟件的最有效方法。不管一個產品是否安全關鍵,這肯定是一個只對其開發團隊有利的結果。
總結
以上是生活随笔為你收集整理的为什么您应该使用基于标准的开发实践的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数字汽车钥匙的安全性增强技术
- 下一篇: 反应式系统实现MQTT客户机