MISRA C++:2023——MISRA? C++ 標(biāo)準(zhǔn)的下一個(gè)版本來(lái)了!為了幫助您了解 MISRA C++:2023相比于之前版本的變化,我們將繼續(xù)為您帶來(lái)Perforce首席技術(shù)支持工程師Frank van den Beuken博士的博客系列,本期為第三篇。
在前兩篇系列文章中,我們向您介紹了新的MISRA C++ 標(biāo)準(zhǔn)和C++簡(jiǎn)史。本文,我們將仔細(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語(yǔ)句的 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)訪問(wèn)代碼塊的次數(shù)時(shí),可以使用for循環(huán)。
C++基于范圍的for循環(huán)是在C++ 11中引入的,作為容器迭代的簡(jiǎn)潔表示法。
傳統(tǒng)的for循環(huán)起源于C語(yǔ)言,具有可選的循環(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è)更為簡(jiǎn)單的表示法。C++語(yǔ)言標(biāo)準(zhǔn)規(guī)定,它是以下語(yǔ)言的縮寫(xiě):
{ auto && __range = v; auto __begin = __range; auto __end = v.end(); for (; __begin != __end; ++__begin) { auto &&s = *__begin; std::cout < s < “ “; } }
但是,此表示法存在局限性。在上面的示例中,__range 是用 v 初始化的,這是一個(gè)更簡(jiǎn)單的變量,但也可以使用為其創(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)用了未定義的行為。問(wèn)題是 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ì)延長(zhǎng)其生命周期。
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)用。
它還建議通過(guò)在range-for循環(huán)之前的單獨(dú)聲明中執(zhí)行內(nèi)部函數(shù)調(diào)用來(lái)解決此問(wèn)題。例如:
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)注意,此問(wèn)題已在C++23 中得到解決,其中初始值設(shè)定項(xiàng)的所有臨時(shí)值的生命周期都擴(kuò)展到整個(gè)for語(yǔ)句。
使用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通過(guò)其標(biāo)準(zhǔn)的合規(guī)模塊為 MISRA C++:2023 規(guī)則提供 100% 的執(zhí)行覆蓋率,該模塊現(xiàn)已推出。通過(guò)靜態(tài)分析工具Helix QAC可查找并報(bào)告C和 C++中違反MISRA規(guī)則和指令的行為。
- END -
文章來(lái)源:https://bit.ly/3VJY8yJ
作者簡(jiǎn)介:
Frank van den Beuken,首席技術(shù)支持工程師
作為技術(shù)支持專家,F(xiàn)rank 在集成 Perforce 靜態(tài)源代碼分析解決方案方面擁有超過(guò) 20 年的經(jīng)驗(yàn),可在客戶軟件開(kāi)發(fā)環(huán)境中進(jìn)行軟件質(zhì)量控制。近年來(lái),他專注于為各種編譯器配置靜態(tài)分析。他還提供代碼質(zhì)量培訓(xùn)和咨詢。Frank 在奈梅亨大學(xué)獲得數(shù)學(xué)和計(jì)算機(jī)科學(xué)博士學(xué)位,研究系統(tǒng)規(guī)范語(yǔ)言。
立即了解為什么Helix QAC是 MISRA C++的最佳靜態(tài)代碼分析器,歡迎咨詢Perforce中國(guó)授權(quán)合作伙伴——龍智:
審核編輯 黃宇
-
靜態(tài)
+關(guān)注
關(guān)注
1文章
29瀏覽量
14586 -
C++
+關(guān)注
關(guān)注
22文章
2114瀏覽量
73873 -
代碼
+關(guān)注
關(guān)注
30文章
4830瀏覽量
69094 -
MISRA
+關(guān)注
關(guān)注
0文章
21瀏覽量
7014
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
embOS的MISRA-C:2012一致性
whitepaper-perforce-what-is-misra
代碼靜態(tài)測(cè)試工具Klocwork 2024.2新發(fā)布
![<b class='flag-5'>代碼</b><b class='flag-5'>靜態(tài)</b>測(cè)試工具Klocwork 2024.2新發(fā)布](https://file1.elecfans.com/web2/M00/00/BE/wKgZomaxo5qAB7NrAAAgMTA8g3Q197.png)
GD32F3使用串口DMA時(shí),相應(yīng)bsp里drv_dma.h文件中含有dma_subperipheral_enum報(bào)未定義錯(cuò)誤的原因?
ESP8266報(bào)錯(cuò)CONFIG_FREERTOS_HZ未定義,怎么解決這個(gè)問(wèn)題?
esp32s2使用自定義中斷,提示UART0未定義,需要包含什么頭文件?
esp-idf-v5.1 vscode提示未定義標(biāo)識(shí)符,F(xiàn)2轉(zhuǎn)到定義路徑不對(duì)是怎么回事?
TLE9879打開(kāi)配置文件以后,發(fā)現(xiàn)會(huì)提示有些未定義的變量,為什么?
stm8的管腳未定義的原因?
帶你走近MISRA C++:2023
![帶你走近<b class='flag-5'>MISRA</b> <b class='flag-5'>C++</b>:<b class='flag-5'>2023</b>](https://file.elecfans.com/web2/M00/52/D4/pYYBAGLNkrKAeFJaAAAjXRuImx0496.png)
MotorControl Workbench 5.x.x安裝在非指定目錄,生成的代碼編譯時(shí)就會(huì)出一大堆的未定義怎么解決?
代碼靜態(tài)測(cè)試工具 Helix QAC 2024.1版新功能解讀
![<b class='flag-5'>代碼</b><b class='flag-5'>靜態(tài)</b>測(cè)試工具 Helix QAC 2024.1版新功能<b class='flag-5'>解讀</b>](https://file.elecfans.com/web2/M00/52/D4/pYYBAGLNkrKAeFJaAAAjXRuImx0496.png)
STM8S2xx直接用IA編譯報(bào)錯(cuò),提示未定義的原因?
使用 MISRA C++:2023? 避免基于范圍的 for 循環(huán)中的錯(cuò)誤
![使用 <b class='flag-5'>MISRA</b> <b class='flag-5'>C++</b>:<b class='flag-5'>2023</b>? 避免基于<b class='flag-5'>范圍</b>的 for <b class='flag-5'>循環(huán)</b>中的錯(cuò)誤](https://file1.elecfans.com/web2/M00/A9/66/wKgZomUl7m-AHJX6AABuJjgxs14678.png)
評(píng)論