背景
C语言诞生至今已有50年,因其语言简洁,语法丰富,可移植性高,和执行效率高等优点,至今仍保持着强大的生命力,在各个行业发挥着作用。
然而C语言的一些优点有时候也是一把双刃剑,在使用者使用不当时反而变成了缺点,主要体现在以下三个方面。首先是一些标准在不同的目标处理器下具有不同的实现和表现,导致可移植性相关的问题;其次是一些程序员容易滥用一些语法,加上C语言高度的灵活性,导致写出不符合预期的代码,或者不容易让阅读者理解的代码;最后则是为了提高运行时的效率,C语言中少有运行时的一些错误检查,这些可能发生的错误需要编程人员自己去规避或解决。
MISRA C
因此C语言编程不难,难在写出清晰易懂、结果符合预期、可移植性高的C代码,尤其在一些对安全性要求很高的行业(如汽车电子等)。为了规范相关从业人员的编程,汽车工业软件可靠性协会(MISRA,Motor Industry)制定了一套针对C语言的编码准则,称为MISRA C。这套标准早期用于提升汽车制造业中嵌入式代码的安全线、可靠性,现在已发展成为编写安全相关C代码的最佳时间,在汽车电子、轨道交通、医疗器械、航空航天等各个领域都被广泛使用。
发展
MISRA 先后发布了三版编码准则,分别是 MISRA C:1998、MISRA C:2004 和 MISRA C:2012。MISRA C:2012(第三版,第一次修订版)发布于 2019 年 2 月,整合了此前发布的 AMD1(修订案 1,MISRA C:2012 的附加安全准则)和 TC1(技术更正 1) 的内容,包含 173 条规则。2020 年 MISRA 发布了修订案 2 (ISO/IEC 9899:2011 核心功能更新),增加了 2 条新的规则。
MISRA C:2012
MISRA C:2012制定了一套C语言编程规范,目的是最大化消除或减少编程错误。其中包含175条编码准则(guideline),分为指令(directive)和规则(rule)。
这175条编码准则可以从使用要求、可判定性、作用域三个方面继续划分,如下表所示。
使用要求 | Mandorary:强制使用,不得违反 Required:要求性,尽量满足 Advisory:建议性 |
可判定性 | 是否可通过阅读代码判定满足要求与否 |
作用域 | 单一翻译单元:可通过独立检查每个翻译单元来检测项目内所有的违反对应准则的行为 系统:需要分析所有的源码来判定是否违反相关准则 |
从代码审核的角度,MISRA C:2012提供了可操作的、量化的评判标准,当然人工审核巨量代码的效率和效果并不理想,也不实际。市面上也有相关的静态分析工具进行代码的自动化检测,支持如MISRA C以及其他的编程规范,进行代码的自动化检测。
从编程人员的角度来说,阅读MISRA C的相关编程规范还是很有裨益的,因为它确实从各个模块具体地提出了多种编程规范/建议,使得编程人员能够更容易写出符合预期的、清晰易懂的C代码。
不过由于手册中假定的工作平台为嵌入式,考虑到硬件配置和运行效率,一些标准在我们看来有写过于严苛。譬如其中一条准则为不允许使用malloc动态分配内存,其潜台词为在嵌入式中为了严格控制内存的使用,一般会在运行前将相关内存事先分配好,或者使用内存池技术进行一整块内存的内部分配、回收管理,以避免内存泄漏或者内存不足导致的内存分配失败问题。
知识点学习
C语言隐式声明 https://www.cnblogs.com/clnchanpin/p/7189554.html
C语言中的volatile 【嵌入式】C语言中volatile关键字_51CTO博客_java volatile关键字
C语言中的字符串结束符 c语言·字符串结束标志 - 知乎
为何不推荐使用goto 为什么说 goto 是一种不好的用法? - 知乎
C语言中的转义字符 C语言——转义字符_c语言转义字符-CSDN博客
函数指针 函数指针的使用_函数指针调用-CSDN博客
不完整类型 百度百科-验证
宏定义中#和##的用法 C语言宏中“#”和“##”的用法_c语言##-CSDN博客
const volatile同时使用 13. 一个参数可以既是const又是volatile吗_const和volatile同时使用_不会编程喵的博客-CSDN博客
参考
什么是 MISRA C:2012 - 知乎
编程规范 之 MISRA C/C++ - 知乎