tag 标签: MISRA C

相关帖子
相关博文
  • 热度 3
    2024-5-15 10:35
    674 次阅读|
    1 个评论
    带你走近MISRA C++:2023
    随着汽车工业迈入数字化转型的新纪元,软件的安全性与可靠性已跃升为设计和开发核心环节的重中之重。MISRA C++标准的诞生与演进,精准地回应了行业发展的需求。自MISRA C++标准首次面世以来,它便被奉为汽车软件工程师在开发实践中的圭臬。 MISRA C++的发展史 MISRA C++的起源可以追溯到MISRA C标准的成功制定和广泛应用。MISRA C是一套针对C语言的编码规范,首次发布于1998年,它迅速成为汽车行业中软件安全性和可靠性的标杆。(回顾MISRA C:2012介绍请见文章 《带你走近MISRA C:2012》 )随着C++在工业界的普及,尤其是在汽车电子控制系统中,对C++的类似规范的需求日益增长。基于MISRA C的成功经验和市场需求,MISRA组织随后发布了适用于C++03标准的编码规范MISRA C++:2008。这是首个针对C++语言的MISRA标准,包含一系列的规则和指导原则,这些规则覆盖了从编程实践到代码设计等多个方面,旨在帮助开发者编写出更加安全和可靠的代码。 MISRA C++:2008规范发布后,得到了业界的广泛认可和采纳。它不仅在汽车行业中得到了应用,还扩展到了航空、医疗设备和工业控制等多个领域,并对这些行业产生了深远的影响。随着C++语言标准的不断更新和新特性的引入,MISRA C++:2008也在经历不断的修订和更新,以保持与C++标准语言的同步,并覆盖新出现的语言特性。 MISRA C++:2008与AUTOSAR C++14 但随着后续新版本C++标准的发布,MISRA C++:2008并未将新的C++语言特性纳入,于是AUTOSAR组织发布了AUTOSAR C++14编码规范。 AUTOSAR C++14在制定时,大量借鉴了MISRA C++:2008的规则。MISRA C++:2008是基于C++03标准制定的,而AUTOSAR C++14则是基于更新的C++14标准。AUTOSAR C++14吸收了约91%的MISRA C++:2008规则,并对其进行了扩展和更新,引入了针对C++11/14特性的规范。 MISRA C++:2023 MISRA C++:2023发布于2023年10月,这是MISRA C++的最新版本。它为使用ISO/IEC 14882:2017定义的2017语言版本(C++:17) 开发的安全关键型软件的组织提供指导。 MISRA C++:2023规则分类 MISRA C++:2023整合了AUTOSAR C++14编码规范, 共179条准则。这些规则按照性质分为两类: Rule(规则)和Directive(指令),包含175条Rule和4条Directive。规则有三种不同类别:” Mandatory(强制)”、” Required(要求)”和“Advisory(建议)”, Mandatory类别的规则中包含5条Rule,Required规则中包含122条Rule和4条Directive,Advisory规则中包含48条Rule。 图1 MISRA C++:2023规则分类 图2 MISRA C++:2023规则类别 MISRA C++:2023还引入了MISRA C++的Rule可判定性分类。可判定性区分标准为是否能在任何情况下明确回答“该代码是否遵循了这条规则?”这个问题。 图3 Rule的可判定性分类 要注意的是,可判定性并不适用于Directive规则。 接下来让我们进一步了解MISRA C++:2023编码规范。 什么是 MISRA C++:2023 Rule 9.5.2,为什么它很重要? MISRA C++:2023 引入了 Rule 9.5.2:“ for 范围初始值设定项最多应包含一个函数调用” ,以避免在基于范围的 for 语句的 for 范围初始值设定项创建临时对象时可能发生的未定义行为。 为了理解为什么会发生这种情况,让我们仔细看看基于 C++ 范围的 for 循环。 什么是 C++ 中基于范围的 for 循环? 在编程中,循环用于重复代码块。当我们知道要在代码块中循环多少次时会使用for循环。C++ 基于范围的 for 循环是在 C++11 中引入的,作为容器迭代的简洁表示法。传统循环源自 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() ) { std::cout << c << " "; } std::cout << std::endl; } 如果我们执行此操作,第一个循环将按预期运行,但第二个循环将调用未定义的行为 。 问题是 createStrings() 有两个函数调用。最里面的调用是 createStrings 的调用 ,最外面的调用是对索引运算符 的调用。 未定义行为的原因是 “ createStrings ”返回的临时对象 用作“ operator ”调用的参数,因此,根据 C++ 的规则,临时对象的生存期不会延长。 MISRA C++:2023 Rule 9.5.2 如何防范未定义的行为 MISRA C++:2023 Rule 9.5.2 旨在防止这种情况。 MISRA C++:2023 引入了规则 9.5.2,该规则要求for范围初始值设定项最多应包含一个函数调用。 它还建议通过在循环范围之前的单独声明中执行内部函数调用来解决此问题。例如: auto strings = createStrings(); for ( auto c: strings ) { std::cout << c << " "; } 现在,初始值设定项中只有一个函数调用,因此生存期扩展具有所需的效果,并且行为已完全定义。 请注意,此问题已在 C++23 中得到解决,其中初始值设定项的所有临时项的生存期已扩展到整个 for 语句。(原文请参考《 Avoiding Bugs in Range-Based For-Loops with MISRA C++:2023®》 ) 关注更多MISRA C++2023内容请见直播回放《汽车行业为何需要MISRA C++:2023》,本期课程我们联合了嵌入式静态分析领域公认的行业领导及先驱Perforce公司,并邀请到其合规总监Jill Britton女士探讨在这项汽车行业调查中的发现并介绍MISRA C++2023为何如此重要。 使用 Helix QAC 执行 MISRA C++:2023 规则 Perforce 的 Helix QAC 是一款静态分析工具,在提供 MISRA C 和 MISRA C++ 合规性检查以及许多其他有价值的分析功能方面处于领先地位。 Helix QAC 通过其标准合规性模块为 MISRA C++:2023 规则提供 100% 的强制执行覆盖率,现已推出。 作为Perforce公司的合作伙伴,北汇信息将为客户提供优质的静态代码测试工具和服务,欢迎您发邮件到marketing@polelink.com,申请Helix QAC免费试用。
  • 热度 9
    2023-8-1 11:10
    613 次阅读|
    0 个评论
    Helix QAC 2023.2 提供 100% 的 MISRA C:2012 和 MISRA C:2023 规则覆盖率,并更新相应的合规性模块以支持 MISRA C:2023。 此外,此版本还包括改进的 C23 语言支持、对Validate平台的改进以及 Helix QAC 和 Validate 的集成,以及其他功能改进。 编码标准覆盖范围(MISRA C:2012、MISRA C:2023 和 CWE) MISRA C:2012, 2023 Helix QAC为MISRA C:2012 AMD 4和MISRA C:2023提供100%的覆盖,将指南先前的revisions、amendments和技术勘误合并为一个单一、全面的版本。MISRA C:2023最近于今年出版。 • M3CM合规模块已更新,以参考MISRA C:2023。 CWE CWE C 和 C++ 合规性模块与最新版本的 CWE 4.11 保持一致。 Perforce Validate 持续的安全和代码合规性平台为嵌入式和任务关键型应用程序提供功能安全性、安全性、可靠性和质量保证。 Validate平台为整个组织的代码库提供分析数据、趋势和配置的集中存储,为所有 Perforce 静态分析产品提供单一管理平台。 2023.2 提供: • 支持Validate中的 Helix QAC 指标。 • 更新了Helix QAC Visual Studio插件,支持与Validate集成。 • 完全支持Validate中的 Helix QAC 自定义消息。 C23 / C++23 语言支持 此版本增加了对以下各项的语言功能支持: • C23 数字分隔符 • C23 / C++23 #elifdef,#enlifndef和#warning指令 产品体验改善 命令行界面 • 允许启用/禁用诊断消息和抑制的同步 • 输出规则组名称和规则ID的新格式说明符%M 图形用户界面 • 允许自定义 RCF 名称和版本 • 允许启用/禁用诊断消息和抑制的同步 HIS指标 • 此版本具有 Helix QAC 增强功能,可直接生成复合 HIS 指标(以前在报告脚本中计算)。 Helix QAC 2023.2 的重要变化 许可证管理更改 RLM v15 服务器的新安装程序与 Helix QAC 2023.2 版本一起提供。 如果将 Helix QAC 与Validate 2023.2 一起使用,则此服务器版本是必需的,否则是可选的。 MISRA C++ 2023 — 新合规模块的早期版本可供预览 MISRA联盟预计将在今年晚些时候发布MISRA C++ 2023编码指南。新标准发布后,将引入新的合规模块以实施执行。在 2023.2 中,合规性模块的早期版本可根据请求提供预览,该模块迄今为止已完成对规则的98% 覆盖。请联系北汇信息以了解更多信息。
  • 热度 8
    2022-10-13 10:48
    1042 次阅读|
    0 个评论
    汽车软件与C语言 随着软件定义汽车概念的兴起,汽车软件开发的工作量开始呈指数级增加,当前车载软件代码量已经达到1亿-3亿行。这是一个什么概念呢,相当于比Windows系统还高出一个数量级。据调查,大部分的车载软件都是使用C语言进行开发,因为C执行效率高、代码量小,因此在汽车的小型控制部件中被广泛使用。尽管C语言在嵌入式系统中如此流行,但仍有很多缺陷: 1. C是弱类型语言 C 是弱类型语言。 在 下面 代码中, char 类型 和 int 类型是可以直接运算的,因为 char 类型会被提升为 int ,这就是 C 中的隐式类型转换,将精度较小的转换为大精度的, 在 这个意义上讲,它并不符合强类型语言的定义。 # include int main ( void ){ char a ='a' ; int b =10 ; int c = a + b; return 0 ; } 2. C有更多操作符及优先级 C相较于其他的语言有更多的操作符,因此其也有更多不同的操作符优先级,其中的大多数都不是能直观判断的,所以通常会被程序员误解。 3. C程序一般不为常见问题提供运行时检查 ,例如运算异常(如零除),溢出,指针的有效性或者数组越界。 MISRA C编码规范 综上所述,C语言对于安全性要求很高的汽车软件而言是不安全的。汽车工业软件可靠性协会(Motor Industry Software Reliability Association,MISRA)在1998年发布了第一版针对汽车工业软件安全性的C语言编码规范---MISRA C, 让程序员有规范可 循 。 从1998年发布的MISRA C:1998,只针对汽车制造业的嵌入式开发,到MISRA C:2012,已经开始扩大覆盖范围到其他高安全性系统。 下面我们就看一下具体的MISRA C:2012规则内容。 MISRA C:2012规则介绍 MISRA C:2012 包含 159 条规则,其中 Directives 有 16 条, Rules 有 143 条。 Dir 4.12: 动态内存分配不应被使用。 图1 Dir 4.12规则 原理:任何库的动态内存分配和进程的释放都可能导致未定义的行为。 Rule 10.3:表达式的值不应分配给具有较窄基本类型或不同基本类型类别的对象。 图2 Rule 10.3规则 原理:C语言允许程序员有相当大的自由度,并允许自动形成不同算术类型之间的赋值。然而,使用这些隐式转换可能会导致意外的结果,可能会丢失值、符号或精度。如MISRA基本类型模型所强制的,使用更强的类型可以降低这些问题发生的可能性。 看到这里,相信大家有许多疑问:为什么一个是Dir而另一个是Rule呢?Category、Analysis这些又是什么呢?下面就来介绍一下MISRA规则的分类和属性。 MISRA C:2012规则分类 MISRA C:2012的规则按照性质分为两类:指令(Directives)和规则(Rules)。规则有三种不同类别:”强制(Mandatory)”、”要求(Required)”和“建议(Advisory)”;其中具体结果如下图所示。 图 3 MISRA C: 2012 规则分类 那么,在任何情况下都可以明确地说明该条代码违反了规则吗? 出于此问题,MISRA C:2012规则的Rules具有可判定性Decidable/Undecidable,他们的区分标准为是否能在任何情况下明确回答“该代码是否遵循了这条规则”? 图 4 MISRA C:2012 规则的可判定性 要注意的是,可判定性并不适用于Directives规则。 Rules 的分析范围 分为 Single Translation Unit/System : 图5 Rules的分析范围 Helix QAC与MISRA C:2012 很明显,MISRA C:2012规则就是为静态测试而生的。 Perforce 公司的静态分析工具 Helix QAC,是汽车行业中主流的静态分析器,其开发团队是MISRA C&C++编码委员会的创始会员,也是MISRA C&C++委员会最具影响力的会员。Helix QAC具有业界领先的编码规范覆盖度,目前MISRA C:2004的编码规范覆盖度达到了99%,而对MISRA C:2012的编码规范覆盖度已达到100%。是嵌入式静态分析领域公认的行业领导及先驱。 图6 Helix QAC的编码规范覆盖度 下面以开源工程wget为例,演示一下Helix QAC是如何定位违反MISRA C:2012规则的代码。 图7 Helix QAC诊断消息0883 诊断消息0883:“包含文件代码不受重复包含的保护”正是MISRAC:2012规则Dir 4.10的映射,通过诊断消息开发人员就可以了解到代码违反MISRA C:2012规则的情况,从而对代码进行修改使其合规。 图8 Rule 9.1规则的不同诊断消息 Rule 9.1:对象在初始化前不能被使用。 图9 Rule 9.1规则 这里大家或许会疑惑,为什么同一个规则下会产生两种诊断消息呢?答案是:数据流分析。 数据流分析是Helix QAC的高级分析,Helix QAC通过内置的数据流分析器 分析运 行 时的 行 为。数据流分析可以识别各种问题,包括可能指示编码错误的条件,以及可能导致程序崩溃的关键未定义 行 为。 我们可以看到图中的诊断消息2962和2963虽然都是Rule 9.1产生的,但是分成了 S uspicious和 A pparent两种。我们在代码中看一下这两条诊断消息的不同。 诊断消息2963的源码如下: 在226行声明了数组saved_lengths,241行对saved_lengths进行赋值操作,在255行使用saved_lengths。但saved_lengths的赋值操作不一定会进行,因为该操作在for循环中进行,如果for循环没有达到执行条件导致并未执行,那么此时saved_lengths就没有初始化。所以此条诊断消息是Suspicious。 诊断消息2962源码如下: 可以看到,在824行声明变量dt,但后面并未对dt进行初始化。所以此条诊断消息是Apparent。 由此可见Helix QAC数据流分析功能的强大。Helix QAC的数据流功能也在不断地更新,在即将到来的新版本2022.4中,数据流计划从Helix QAC引擎中分离出来,成为自己的组件。 在近期发布的最新版本Helix QAC 2022.3中, 引入了对微软Visual Studio 2022的支持 , 提供更广泛的编译器支持, 以及对C++20和C23的升级语言支持。 此外, 此版本具有使用“qainject”自动生成 CCT 的功能,可简化构建理解和编译器设置 。 作为Perforce公司的合作伙伴,北汇信息将为客户提供优质的静态代码测试工具和服务 。