MISRA C++:2023——MISRA? C++ 標(biāo)準(zhǔn)的下一個(gè)版本來了!為了幫助您了解 MISRA C++:2023相比于之前版本的變化,我們將繼續(xù)為您帶來Perforce首席技術(shù)支持工程師Frank van den Beuken博士的博客系列,本期為第三篇。
在前兩篇系列文章中,我們向您介紹了新的MISRA C++ 標(biāo)準(zhǔn)和C++簡史。本文,我們將仔細(xì)研究C++中以for循環(huán)為中心的特定規(guī)則。
什么是MISRA C++:2023規(guī)則9.5.2,為什么它很重要?
MISRA C++:2023 引入了規(guī)則 9.5.2 “for-range 初始值設(shè)定項(xiàng)最多應(yīng)包含一個(gè)函數(shù)調(diào)用”,以避免在基于范圍的for語句的 for-range初始值設(shè)定項(xiàng)創(chuàng)建臨時(shí)對(duì)象時(shí)可能發(fā)生的未定義行為。
要了解為什么會(huì)發(fā)生這種情況,讓我們仔細(xì)看看基于C++范圍的for循環(huán)。
C++中基于范圍的for循環(huán)是什么?
在編程中,循環(huán)用于重復(fù)代碼塊。當(dāng)您知道要循環(huán)訪問代碼塊的次數(shù)時(shí),可以使用for循環(huán)。
C++基于范圍的for循環(huán)是在C++ 11中引入的,作為容器迭代的簡潔表示法。
傳統(tǒng)的for循環(huán)起源于C語言,具有可選的循環(huán)初始化,然后是循環(huán)條件,最后是循環(huán)增量表達(dá)式。
傳統(tǒng)for循環(huán)可用于迭代容器,如下所示:
std::vector v = { "Example", "vector", "of", "strings" }; for ( auto &&i = v.begin(); i != v.end(); ++i ) { std::cout < *i < “ “; } std::cout < std::endl;
使用基于范圍的for循環(huán),迭代器的使用是隱式的:
for ( auto &&s: v ) { std::cout < s < “ “; }
對(duì)于同一循環(huán),這是一個(gè)更為簡單的表示法。C++語言標(biāo)準(zhǔn)規(guī)定,它是以下語言的縮寫:
{ auto && __range = v; auto __begin = __range; auto __end = v.end(); for (; __begin != __end; ++__begin) { auto &&s = *__begin; std::cout < s < “ “; } }
但是,此表示法存在局限性。在上面的示例中,__range 是用 v 初始化的,這是一個(gè)更簡單的變量,但也可以使用為其創(chuàng)建多個(gè)臨時(shí)對(duì)象的復(fù)雜表達(dá)式。
讓我們考慮使用一個(gè)函數(shù),該函數(shù)返回字符串的向量,并具有:
一個(gè)循環(huán),輸出以空格分隔的字符串,如上所述
打印第一個(gè)字符串的字母的第二個(gè)循環(huán),用空格分隔:
std::vector createStrings() { return { "Example”, "vector", "of", "strings" }; } int main() { for ( auto w: createStrings() ) { std::cout < w < " "; } std::cout < std::endl; for ( auto c: createStrings()[0] ) { std::cout < c < " "; } std::cout < std::endl; }
如果我們執(zhí)行此操作,第一個(gè)循環(huán)將按預(yù)期運(yùn)行,但第二個(gè)循環(huán)卻調(diào)用了未定義的行為。問題是 createStrings()[0] 有兩個(gè)函數(shù)調(diào)用。最里面的調(diào)用是對(duì) createStrings 的調(diào)用,最外層的調(diào)用是對(duì)索引運(yùn)算符 []的調(diào)用。
出現(xiàn)未定義行為的原因是,“createStrings”返回的臨時(shí)對(duì)象被用作“operator[]”調(diào)用的參數(shù),因此,根據(jù)C++的規(guī)則,臨時(shí)對(duì)象不會(huì)延長其生命周期。
MISRA C++:2023規(guī)則9.5.2 如何防范未定義行為
MISRA C++:2023規(guī)則 9.5.2 旨在防止這種情況。MISRA C++:2023引入了規(guī)則 9.5.2,該規(guī)則要求for-range-initializer應(yīng)最多包含一個(gè)函數(shù)調(diào)用。
它還建議通過在range-for循環(huán)之前的單獨(dú)聲明中執(zhí)行內(nèi)部函數(shù)調(diào)用來解決此問題。例如:
auto strings = createStrings(); for ( auto c: strings[0] ) { std::cout < c < " "; }
現(xiàn)在,初始值設(shè)定項(xiàng)中只有一個(gè)函數(shù)調(diào)用,因此生命周期擴(kuò)展就能達(dá)到預(yù)期效果,并且行為已完全定義。
請(qǐng)注意,此問題已在C++23 中得到解決,其中初始值設(shè)定項(xiàng)的所有臨時(shí)值的生命周期都擴(kuò)展到整個(gè)for語句。
使用Perforce Helix QAC強(qiáng)制執(zhí)行MISRA C++:2023 規(guī)則
Perforce的 Helix QAC 是一款靜態(tài)代碼分析工具,在提供 MISRA C 和 MISRA C++ 合規(guī)性檢查以及許多其他有價(jià)值的分析功能方面處于領(lǐng)先地位。
Helix QAC通過其標(biāo)準(zhǔn)的合規(guī)模塊為 MISRA C++:2023 規(guī)則提供 100% 的執(zhí)行覆蓋率,該模塊現(xiàn)已推出。通過靜態(tài)分析工具Helix QAC可查找并報(bào)告C和 C++中違反MISRA規(guī)則和指令的行為。
- END -
文章來源:https://bit.ly/3VJY8yJ
作者簡介:
Frank van den Beuken,首席技術(shù)支持工程師
作為技術(shù)支持專家,F(xiàn)rank 在集成 Perforce 靜態(tài)源代碼分析解決方案方面擁有超過 20 年的經(jīng)驗(yàn),可在客戶軟件開發(fā)環(huán)境中進(jìn)行軟件質(zhì)量控制。近年來,他專注于為各種編譯器配置靜態(tài)分析。他還提供代碼質(zhì)量培訓(xùn)和咨詢。Frank 在奈梅亨大學(xué)獲得數(shù)學(xué)和計(jì)算機(jī)科學(xué)博士學(xué)位,研究系統(tǒng)規(guī)范語言。
立即了解為什么Helix QAC是 MISRA C++的最佳靜態(tài)代碼分析器,歡迎咨詢Perforce中國授權(quán)合作伙伴——龍智:
審核編輯 黃宇
-
靜態(tài)
+關(guān)注
關(guān)注
1文章
29瀏覽量
14542 -
C++
+關(guān)注
關(guān)注
22文章
2108瀏覽量
73618 -
代碼
+關(guān)注
關(guān)注
30文章
4779瀏覽量
68521 -
MISRA
+關(guān)注
關(guān)注
0文章
21瀏覽量
6963
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論