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

本文主要是介绍Perforce静态代码分析专家解读MISRA C++:2023®新标准:如何安全、高效地使用基于范围的for循环,防范未定义行为,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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规则和指令的行为。

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

作者简介:

图片

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

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

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

官网:www.shdsd.com

电话:400-666-7732

邮箱:marketing@shdsd.com

这篇关于Perforce静态代码分析专家解读MISRA C++:2023®新标准:如何安全、高效地使用基于范围的for循环,防范未定义行为的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1072248

相关文章

Java使用Javassist动态生成HelloWorld类

《Java使用Javassist动态生成HelloWorld类》Javassist是一个非常强大的字节码操作和定义库,它允许开发者在运行时创建新的类或者修改现有的类,本文将简单介绍如何使用Javass... 目录1. Javassist简介2. 环境准备3. 动态生成HelloWorld类3.1 创建CtC

使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解

《使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解》本文详细介绍了如何使用Python通过ncmdump工具批量将.ncm音频转换为.mp3的步骤,包括安装、配置ffmpeg环... 目录1. 前言2. 安装 ncmdump3. 实现 .ncm 转 .mp34. 执行过程5. 执行结

Java使用jar命令配置服务器端口的完整指南

《Java使用jar命令配置服务器端口的完整指南》本文将详细介绍如何使用java-jar命令启动应用,并重点讲解如何配置服务器端口,同时提供一个实用的Web工具来简化这一过程,希望对大家有所帮助... 目录1. Java Jar文件简介1.1 什么是Jar文件1.2 创建可执行Jar文件2. 使用java

C++统计函数执行时间的最佳实践

《C++统计函数执行时间的最佳实践》在软件开发过程中,性能分析是优化程序的重要环节,了解函数的执行时间分布对于识别性能瓶颈至关重要,本文将分享一个C++函数执行时间统计工具,希望对大家有所帮助... 目录前言工具特性核心设计1. 数据结构设计2. 单例模式管理器3. RAII自动计时使用方法基本用法高级用法

C#使用Spire.Doc for .NET实现HTML转Word的高效方案

《C#使用Spire.Docfor.NET实现HTML转Word的高效方案》在Web开发中,HTML内容的生成与处理是高频需求,然而,当用户需要将HTML页面或动态生成的HTML字符串转换为Wor... 目录引言一、html转Word的典型场景与挑战二、用 Spire.Doc 实现 HTML 转 Word1

Java中的抽象类与abstract 关键字使用详解

《Java中的抽象类与abstract关键字使用详解》:本文主要介绍Java中的抽象类与abstract关键字使用详解,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、抽象类的概念二、使用 abstract2.1 修饰类 => 抽象类2.2 修饰方法 => 抽象方法,没有

MyBatis ParameterHandler的具体使用

《MyBatisParameterHandler的具体使用》本文主要介绍了MyBatisParameterHandler的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参... 目录一、概述二、源码1 关键属性2.setParameters3.TypeHandler1.TypeHa

Spring 中的切面与事务结合使用完整示例

《Spring中的切面与事务结合使用完整示例》本文给大家介绍Spring中的切面与事务结合使用完整示例,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考... 目录 一、前置知识:Spring AOP 与 事务的关系 事务本质上就是一个“切面”二、核心组件三、完

使用docker搭建嵌入式Linux开发环境

《使用docker搭建嵌入式Linux开发环境》本文主要介绍了使用docker搭建嵌入式Linux开发环境,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录1、前言2、安装docker3、编写容器管理脚本4、创建容器1、前言在日常开发全志、rk等不同

使用Python实现Word文档的自动化对比方案

《使用Python实现Word文档的自动化对比方案》我们经常需要比较两个Word文档的版本差异,无论是合同修订、论文修改还是代码文档更新,人工比对不仅效率低下,还容易遗漏关键改动,下面通过一个实际案例... 目录引言一、使用python-docx库解析文档结构二、使用difflib进行差异比对三、高级对比方