0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Perforce静态代码分析专家解读MISRA C++:2023®新标准:如何安全、高效地使用基于范围的for循环,防范未定义行

龙智 来源:jf_15970448 作者:jf_15970448 2024-06-18 12:57 次阅读

MISRA C++:2023——MISRA® C++ 标准的下一个版本来了!为了帮助您了解 MISRA C++:2023相比于之前版本的变化,我们将继续为您带来Perforce首席技术支持工程师Frank van den Beuken博士的博客系列,本期为第三篇。

在前两篇系列文章中,我们向您介绍了新的MISRA C++ 标准C++简史。本文,我们将仔细研究C++中以for循环为中心的特定规则。

什么是MISRA C++:2023规则9.5.2,为什么它很重要?

MISRA C++:2023 引入了规则 9.5.2 “for-range 初始值设定项最多应包含一个函数调用”,以避免在基于范围的for语句的 for-range初始值设定项创建临时对象时可能发生的未定义行为。

要了解为什么会发生这种情况,让我们仔细看看基于C++范围的for循环。

C++中基于范围的for循环是什么?

编程中,循环用于重复代码块。当您知道要循环访问代码块的次数时,可以使用for循环。

C++基于范围的for循环是在C++ 11中引入的,作为容器迭代的简洁表示法。

传统的for循环起源于C语言,具有可选的循环初始化,然后是循环条件,最后是循环增量表达式。

传统for循环可用于迭代容器,如下所示:

std::vector v = { "Example", "vector", "of", "strings" }; for ( auto &&i = v.begin(); i != v.end(); ++i ) {   std::cout < < *i < < “ “; } std::cout < < std::endl;

使用基于范围的for循环,迭代器的使用是隐式的:

for ( auto &&s: v ) {   std::cout < < s < < “ “; }

对于同一循环,这是一个更为简单的表示法。C++语言标准规定,它是以下语言的缩写:

{   auto && __range = v;   auto __begin = __range;   auto __end = v.end();    for (; __begin != __end; ++__begin) {     auto &&s = *__begin;     std::cout < < s < < “ “;   } }

但是,此表示法存在局限性。在上面的示例中,__range 是用 v 初始化的,这是一个更简单的变量,但也可以使用为其创建多个临时对象的复杂表达式。

让我们考虑使用一个函数,该函数返回字符串的向量,并具有:

一个循环,输出以空格分隔的字符串,如上所述

打印第一个字符串的字母的第二个循环,用空格分隔:

std::vector< std::string > 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; }

如果我们执行此操作,第一个循环将按预期运行,但第二个循环却调用了未定义的行为。问题是 createStrings()[0] 有两个函数调用。最里面的调用是对 createStrings 的调用,最外层的调用是对索引运算符 []的调用。

出现未定义行为的原因是,“createStrings”返回的临时对象被用作“operator[]”调用的参数,因此,根据C++的规则,临时对象不会延长其生命周期。

MISRA C++:2023规则9.5.2 如何防范未定义行为

MISRA C++:2023规则 9.5.2 旨在防止这种情况。MISRA C++:2023引入了规则 9.5.2,该规则要求for-range-initializer应最多包含一个函数调用。

它还建议通过在range-for循环之前的单独声明中执行内部函数调用来解决此问题。例如:

auto strings = createStrings(); for ( auto c: strings[0] ) { std::cout < < c < < " "; }

现在,初始值设定项中只有一个函数调用,因此生命周期扩展就能达到预期效果,并且行为已完全定义。

请注意,此问题已在C++23 中得到解决,其中初始值设定项的所有临时值的生命周期都扩展到整个for语句。

使用Perforce Helix QAC强制执行MISRA C++:2023 规则

Perforce的 Helix QAC 是一款静态代码分析工具,在提供 MISRA C 和 MISRA C++ 合规性检查以及许多其他有价值的分析功能方面处于领先地位。

Helix QAC通过其标准的合规模块为 MISRA C++:2023 规则提供 100% 的执行覆盖率,该模块现已推出。通过静态分析工具Helix QAC可查找并报告C和 C++中违反MISRA规则和指令的行为。

- END -

文章来源:https://bit.ly/3VJY8yJ

作者简介:

Frank van den Beuken,首席技术支持工程师

作为技术支持专家,Frank 在集成 Perforce 静态源代码分析解决方案方面拥有超过 20 年的经验,可在客户软件开发环境中进行软件质量控制。近年来,他专注于为各种编译器配置静态分析。他还提供代码质量培训和咨询。Frank 在奈梅亨大学获得数学和计算机科学博士学位,研究系统规范语言。

立即了解为什么Helix QAC是 MISRA C++的最佳静态代码分析器,欢迎咨询Perforce中国授权合作伙伴——龙智:

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 静态
    +关注

    关注

    1

    文章

    29

    浏览量

    14542
  • C++
    C++
    +关注

    关注

    22

    文章

    2108

    浏览量

    73618
  • 代码
    +关注

    关注

    30

    文章

    4779

    浏览量

    68519
  • MISRA
    +关注

    关注

    0

    文章

    21

    浏览量

    6963
收藏 人收藏

    评论

    相关推荐

    embOS的MISRA-C:2012一致性

    MISRA C是汽车工业软件可靠性协会(MISRA)开发的一套针对C编程语言的软件开发指南,目的是提升嵌入式系统的安全性和可移植性。2012
    的头像 发表于 08-20 11:35 477次阅读

    whitepaper-perforce-what-is-misra

    如果您熟悉嵌入式软件的世界,您可能听说过安全关键系统的MISRA编码准则和合规性。最初为在汽车嵌入式软件行业,MISRA C for C
    发表于 08-08 15:54 0次下载

    ESP8266报错CONFIG_FREERTOS_HZ未定义,怎么解决这个问题?

    SDK用的是EPS8266_RTOS_SDK,在github上下载的最新版在vscode 上用这个函数时vTaskDelay(1000 / portTICK_PERIOD_MS);portTICK_PERIOD_MS报错,提示CONFIG_FREERTOS_HZ未定义,在文件里面没找到这个宏
    发表于 06-19 06:06

    esp32s2使用自定义中断,提示UART0未定义,需要包含什么头文件?

    | ESP_INTR_FLAG_IRAM, &handle);static void IRAM_ATTR uart0_irq_handler(void *arg) { uint16_t status = UART0.int_st.val; } 提示UART0未定义,不知道需要包含什么头文件。
    发表于 06-18 06:25

    stm8的管脚未定义的原因?

    我使用IAR编译的时候,包含了iostm8s103f3.h,定义管脚时使用的是_BoolLED@PB_ODR:5;为什么提示我——Bool未定义
    发表于 05-15 06:00

    带你走近MISRA C++:2023

    随着汽车工业迈入数字化转型的新纪元,软件的安全性与可靠性已跃升为设计和开发核心环节的重中之重。MISRAC++标准的诞生与演进,精准地回应了行业发展的需求。自MISRAC++标准首次面世以来,它便被
    的头像 发表于 04-30 08:24 1799次阅读
    带你走近<b class='flag-5'>MISRA</b> <b class='flag-5'>C++</b>:<b class='flag-5'>2023</b>

    MotorControl Workbench 5.x.x安装在非指定目录,生成的代码编译时就会出一大堆的未定义怎么解决?

    如果MotorControl Workbench 5.x.x安装在非指定目录,比如e:STMicroelectronicsMC_SDK_5.x.x,生成的代码编译时就会出一大堆的未定义。这个需要如何设置才能正确编译?(编译软件就安装的程序都没问题,改到默认目录安装就不会出
    发表于 04-26 06:58

    代码静态测试工具 Helix QAC 2024.1版新功能解读

    新的问题列表的CSV下载选项。 此版本还包括对于C/C++的CWE、C的HKMC和MISRA C++:2
    的头像 发表于 04-25 12:32 596次阅读
    <b class='flag-5'>代码</b><b class='flag-5'>静态</b>测试工具 Helix QAC 2024.1版新功能<b class='flag-5'>解读</b>

    STM8S2xx直接用IA编译报错,提示未定义的原因?

    大家有没有遇到官方的STM8S2xx的触摸例程直接用IA编译报错,提示未定义
    发表于 04-16 07:13

    使用 MISRA C++2023® 避免基于范围的 for 循环中的错误

    在前两篇博客中,我们 向您介绍了新的 MISRA C++ 标准 和 C++ 的历史 。在这篇博客中,我们将仔细研究以 C++ 中 for 
    的头像 发表于 03-28 13:53 782次阅读
    使用 <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'>循环</b>中的错误

    已经将文件的路径添加了,头文件也包含了,为什么编译会提示未定义符号错误?

    我准备添加TFT显示屏的驱动,已经将文件的路径添加了,头文件也包含了,但在编译时却提示未定义符号错误。
    发表于 03-07 07:36

    汽车电子行业的MISRA C标准解读

    之前分享了一些编程规范相关的文章,有位读者提到了汽车电子行业的MISRA C标准,说这个很不错。
    的头像 发表于 01-17 11:03 1183次阅读

    代码静态测试工具Helix QAC 2023.4新发布

    Helix QAC 2023.4 为新的 MISRA C++2023 指南推出了 100% MISRA C++
    的头像 发表于 01-13 12:25 488次阅读
    <b class='flag-5'>代码</b><b class='flag-5'>静态</b>测试工具Helix QAC 2023.4新发布

    C++简史:C++是如何开始的

    MISRA C++2023MISRA® C++ 标准的下一个版本,来了!为了帮助您做好准备,
    的头像 发表于 01-11 09:00 578次阅读
    <b class='flag-5'>C++</b>简史:<b class='flag-5'>C++</b>是如何开始的

    Helix QAC—软件静态测试工具

    Helix QAC是Perforce公司(原PRQA公司)产品,主要用于C/C++代码的自动化静态分析
    的头像 发表于 01-10 17:35 654次阅读
    Helix QAC—软件<b class='flag-5'>静态</b>测试工具