代码质量与安全 | MISRA C++:2023® 新标准:如何安全使用基于范围的for循环
MISRA C++:2023——MISRA® C++ 标准的下一个版本来了!为了帮助您了解 MISRA C++:2023相比于之前版本的变化,我们将继续为您带来Perforce首席技术支持工程师Frank van den Beuken博士的博客系列,本期为第三篇。

什么是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 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 的调用,最外层的调用是对索引运算符 [] 的调用。
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 –
立即了解为什么Helix QAC是 MISRA C++的最佳静态代码分析器,欢迎咨询Perforce中国授权合作伙伴——龙智: