MISRA
The Motor Industry Software Reliability Association
MISRA-C-:2004
Guidelines
for the use
of the
C language
in critical systems
中文版
1 背景 —— C 的使用和问题 ........................................................................................ 3
1.1 汽车工业中 C 的使用.......................................................................................................... 3
1.2 语言的不安全性和 C 语言.................................................................................................. 3
1.3 安全相关系统中 C 的使用.................................................................................................. 4
1.4 标准化 .................................................................................................................................. 5
2 MISRA-C:视野.......................................................................................................... 6
2.1 MISRA-C 的发布说明........................................................................................................ 6
2.2 MISRA-C 的目标................................................................................................................ 6
3 MISRA-C:范围.......................................................................................................... 7
3.1 基本的语言问题 .................................................................................................................. 7
3.2 未指出的问题 ...................................................................................................................... 7
3.3 可应用性 .............................................................................................................................. 7
3.4 预备知识 .............................................................................................................................. 7
3.5
C++问题............................................................................................................................... 7
3.6 自动产生代码的问题 .......................................................................................................... 8
4 使用 MISRA-C............................................................................................................. 9
4.1 软件工程环境 ...................................................................................................................... 9
4.2 编程语言和编码环境 .......................................................................................................... 9
4.3 采用子集(subset).......................................................................................................... 11
4.4 符合性声明(Claiming compliance) ............................................................................ 13
4.5 持续改进 ............................................................................................................................ 13
5 规则简介 ..................................................................................................................... 14
5.1 规则分类 ............................................................................................................................ 14
5.2 规则的组织 ........................................................................................................................ 14
5.3 规则的冗余 ........................................................................................................................ 14
5.4 规则的形式 ........................................................................................................................ 14
5.5 理解原始参考 .................................................................................................................... 15
5.6 规则的范围 ........................................................................................................................ 17
6 规则 ............................................................................................................................. 18
6.1 环境 .................................................................................................................................... 18
6.2 语言扩展 ............................................................................................................................ 19
6.3 文档 .................................................................................................................................... 19
6.4 字符集 ................................................................................................................................ 21
6.5 标识符 ................................................................................................................................ 21
1
6.6 类型 .................................................................................................................................... 23
6.7 常量 .................................................................................................................................... 24
6.8 声明与定义 ........................................................................................................................ 25
6.9 初始化 ................................................................................................................................ 27
6.10
数值类型转换 ................................................................................................................ 27
6.11 指针类型转换 .................................................................................................................... 36
表达式 ............................................................................................................................ 37
6.12
控制语句表达式 ............................................................................................................ 43
6.13
6.14
控制流 ............................................................................................................................ 45
switch 语句......................................................................................................................... 48
6.15
6.16
函数 ................................................................................................................................ 50
指针和数组 .................................................................................................................... 51
6.17
结构与联合 .................................................................................................................... 54
6.18
6.19
预处理指令 .................................................................................................................... 57
标准库 ............................................................................................................................ 62
6.20
6.21
运行时错误 .................................................................................................................... 64
7 References................................................................................................................... 66
Appendix A: Summary of rules....................................................................................... 68
Appendix B:MISRA-C :1998 到
MISRA-C :2004 规则映射 .............. 74
Appendix C:MISRA-C:1998 – 已废除的规则 .............................................................. 81
Appendix D:ISO 标准交互参考.................................................................................... 82
Appendix E : 术语表 ....................................................................................................... 85
2
1 背景 —— C 的使用和问题
1.1 汽车工业中 C 的使用
MISRA-C:1998 [1] 发布于 1998 年。本文档是它的修订版本,用来解决与第一版本有关系
的问题。
在汽车工业领域的实时嵌入式应用中,C 编程语言的使用越来越体现出广泛性和重要性。
这在相当程度上取决于该语言固有的灵活性、可支持的范围及其潜在的访问广泛硬件环境的
可移植性。详细的理由包括:
对于许多使用中的微处理器来说,如果存在其他除了汇编语言之外的可用语言,通
常就是 C。在许多情况下,其他语言根本就不可用于硬件。
C 对高速、底层、输入/输出操作等提供了很好的支持,而这些特性是许多汽车嵌入
式系统的基本特性。
由于应用的逐步增长的复杂性,高级语言的使用较汇编语言更为适合。
相对于其他一些高级语言,C 能够产生较小的和较少 RAM 密集性(RAM-intensive)
的代码。
增长的可移植性需求。市场竞争要求在工程项目生命周期的任何阶段,软件可以通
过移植到新的和/或低成本的处理器,目的是为了降低硬件成本。
增长的自动产生 C 代码的使用要求。C 代码需要从模型包中自动产生。
增长的对开放系统和主机环境(hosted enviroments)的兴趣。
1.2 语言的不安全性和 C 语言
没有哪种编程语言能够保证最终的可执行代码会准确地按照程序员预想的那样执行。任
何语言都会产生大量的问题,下面为其做了广泛的分类,并描述了 C 语言不安全性的例子。
1.2.1 程序员产生错误
程序员产生的错误,简单的可以是变量名字的书写错误,或者更为复杂的错误,如对算
法的误解。编程语言可以承受这样的错误。首先,语言的风格和表达能帮助或提示程序员清
晰考虑其算法。其次,对于书写错误,语言可以使从一个有效结构向另一个有效(不是预想
的)结构的转换变得轻松或困难。第三,当错误发生时,语言可以检测到也可能检测不到。
首先,关于语言的风格和表达,使用 C 可以编写出良好布局的、结构化的和表达性强的
代码。还可以使用它编写出不正当的和特别难以理解的代码。很明显,后者对于安全相关的
系统是不可接受的。
其次,C 的语法特性足以使得书写错误也能产生完全有效的代码。例如,在“==”(逻
辑比较)的地方写成“=”(赋值)是很常见的,而且最终结果也几乎总是有效的(但它是错
误的);而 if 语句的结尾出现的多余分号能完全改变代码逻辑。
第三,C 的基本观点是假设程序员知道他们在做什么,这意味着错误即使出现也不会被语
言注意到而通过。在这方面 C 体现出的软弱性正在于它的“书写检查”(type checking)。举例
来说,C 不会拒绝程序员在使用整数代表 true/false 值时却在该整数中存储了浮点值。大多数
这样的失配可以简单地通过强制使其合适。如果 C 的表现不得其所(a square peg and a round),
3
它不会挑剔而会适合它们!
1.2.2 程序员不了解语言
程序员可能会误解语言构造的作用。对这样的误解,一些语言是更为开放的。
C 语言中有相当多的地方能使程序员轻易产生误解。例如运算符优先级的规则。这些规则
是良好定义的,但也非常复杂,也很容易对某特定表达式中运算符的优先级做出错误的假设。
1.2.3 编译器的行为同程序员预期的不同
如果语言具有未经完善定义的特性,或者模糊特性,那么在程序员认为某个构造应该如
此时,编译器的解释却是完全不同的。
C 语言中许多地方是未经完善定义的,因此其行为可能会随着编译器的改变而改变。某些
情况下,其行为甚至在同一个编译器内也会根据上下文而发生变化。Annex G 中所有的 C 标
准列出了 201 个这种问题。这可以提出相当多的问题,特别是在面临编译器间的移植性时。
然而,C 标准 [2] 列出了这些问题,所以它们能为我们所知。
1.2.4 编译器包含错误
语言的编译器(及其链接器等)本身就是软件工具。编译器可能不会始终正确地编译代
码。例如,在特定环境下它们可能同语言标准相违背,或者其本身可能就包含“bug”。
因为 C 语言中存在许多难以理解的地方,编译器的编写者很容易错误地解释和实现标准。
语言的某些地方比其他的更容易这样。而且编译器的编写者有时会有意改变标准。
1.2.5 运行时错误
有些不同的语言问题产生自正确编译的代码,但某些特殊数据会在代码运行时产生错误。
语言能够对可执行代码内部做运行时的检查以检测这样的错误并执行适当的动作。
通常,C 的运行时检查能力比较弱。这也是 C 代码短小有效的原因之一,但是在运行中
检查错误就要花费一定的代价。C 编译器通常不为某些常见问题提供运行时检查,诸如数学异
常(如零除)、溢出、指针地址的有效性,或数组越界错误。
1.3 安全相关系统中 C 的使用
从 1.2 节可以清楚地知道,在安全相关系统中使用 C 语言需要相当小心。针对上面提及的
问题种类,已经为安全相关系统中 C 的使用提出了许多需要关注的事情。显然地,不能为安
全相关系统使用所有的 C 语言特性。
然而,做为语言来说,C 是非常成熟的,在实践中也是经过了良好分析和使用的。所以它
的不足也是众所周知和可以理解的。同时可获得大量的商业工具支持,这些工具用来静态检
查 C 源代码和提醒程序员语言问题的存在。
如果为了实践的原因有必要在安全相关系统中使用 C 语言,那么必须对语言的使用加以
限制,避免那些确实可以产生问题的地方,直到它是可以应用的。本文档为人们提供了这样
的限制集合(通常称为“语言子集”(language subset))。
Hatton [3] 认为,倘若强加了“……严格和自动的强制性约束……”,那么 C 能够写出“……
至少同其他通用语言一样的具有高质量和一致性的软件”。
注意,相对于 C 语言,汇编语言不再适合于安全相关系统,在某些方面还会更坏。通常
不建议在安全相关系统中使用汇编语言,即使使用也要加以非常严格的约束。
4
1.4 标准化
本 文 档 使 用 的 标 准 是 由 ISO 9899:1990 [2] 定 义 的 C 编 程 语 言 , 它 是 由 ISO/IEC
9899/COR1:1995 [4]、ISO/IEC 9899/AMD1:1995 [5]和 ISO/IEC 9899/COR2:1996 [6]修订的。为
了简便,本文档中统称为“C90”。基本的 1990 年文档[7]是 ANSI X3.159-1989 [2]的 ISO 版本。
在内容上,ISO/IEC 标准同 ANSI 标准是一致的。然而要说明的是,两个标准中章节的编号是
不同的,本文档的章节编号随同 ISO 标准。
还要说明的是,ANSI 标准[7]包含了一个有用的附录,其中在某些由标准委员会制定的决
策后给出了相关的说明解释。ISO 版本中没有这样的附录。
工作小组已经开始考虑 ISO/IEC 9899:1999[8](称为“C99”)。在本文档的发布日期(2004
年 10 月),还没出现嵌入了 C99 的商业编译器。
5
2 MISRA-C:视野
2.1 MISRA-C 的发布说明
MISRA 协会在 1994 年发布了它的“Development Guidelines for Vehicle Based Software”[9],
描述了软件开发过程中所有应该使用的方法集。特别地,在使用中因为考虑安全集成度而做
出的语言、编译器和语言特性的选择,成为首要考虑的事情。MISRA 指南[9]中的节 3.2.4.3(b)
和表 3 描述了这些。推荐的方法之一是使用已经应用于航空、能源和国防工业中的标准化的
语言子集。本文档定义了这样一个合适的 C 语言子集。
2.2 MISRA-C 的目标
在发布这个关于 C 编程语言使用的文档时,MISRA 协会并没想促进 C 在汽车工业中的应
用,而是因为认识到了 C 的广泛应用。本文档的目标是为了促进该语言的最为安全的使用。
MISRA 协会希望本文档能获得工业上的接受,以及对更安全子集的采用能够成为汽车制
造业和许多零部件供应商的最佳实践。它也应该为通用 C 和该特殊子集的使用增加培训和增
强使用能力,无论是在个人层次还是公司范围。
大部分重点放在了静态检查工具上以强制对子集的适应,同时希望这也会成为汽车嵌入
式系统开发者的普遍实践。
尽管许多学术著作对语言及其正反两面做了大量的描述,但这方面信息在汽车开发中还
不是广为人知。本文档的另外一个目标就是使汽车工业中的工程师和经理们越来越多地关心
语言的选用问题。
可以帮助进行软件开发的工具,尤其是支持 C 语言使用的工具对我们来说是个好处。然
而,对设计与实现的鲁棒性的关注是始终存在的,特别是对安全相关软件的开发。人们希望
汽车工业中正在使用的实现软件最佳实践(通过 MISRA 指南[9]和本文档)的方法能鼓励
COTS 工具的供应商使用它以保证其产品适合于汽车工业应用。
6
3 MISRA-C:范围
3.1 基本的语言问题
MISRA 指南[9](表 3)要求使用“标准化结构化语言的受限子集”。对 C 来说,这意味
着只能使用在 ISO 标准中定义的语言,因此排除了以下方面的使用:
K&R C(由 Kernighan 和 Ritchie 编写的“The C Programming language”的第一版)
C++
C 的私有扩展
3.2 未指出的问题
风格和代码度量问题在一定程度上是很个人化的。对任何一群人来说都很难赞成什么是
适当的,而要 MISRA 给出确定性的建议也是不合适的。重要的不是使用者采取了哪种确切的
风格或者特定的度量,而是使用者要定义风格指南和合适的度量与限制(见节 4.2.2 和 4.2.4)。
MISRA 协会的角色不是建议特定的供应商或工具强制执行所采取的约束。使用本文档的
用户在选择工具上是自由的,鼓励供应商提供遵循规则的工具。本文档用户的负担是要声明
其工具充分地遵循了规则。
3.3 可应用性
本文档被设计为应用在汽车嵌入式系统的产品代码上。
根据 ISO 9899[2](节 5.1.2)中定义的执行环境,本文档的目标定在“自立(free-standing)
的环境”,尽管它也描述了库的问题,因为嵌入式编译器中经常也会用到一些标准库。
如果合适,本文档的大部分要求也可以应用在其他嵌入式领域。对主机系统(hosted
system)的应用,本文档的要求不是必需的。
在进行编译器和静态工具的比较检测(benchmark)时也不需完全应用本文档规则,有时
在比较工具时有必要打破这些规则,以测量工具的响应。
3.4 预备知识
本文档不是要做为所涉主题的介绍和培训。而是认为读者熟悉 ISO C 编程语言标准和相
关工具,并读过了主要的引用文档。同样假设读者已经接受了适当的培训并胜任 C 程序员工
作。
3.5 C++问题
C++不同于 C 语言,本文档的范围不包含它,也不试图讲解 C++对于编写安全相关系统
的适合性与否。然而对于 C++编译器和代码的使用方面应该给出以下说明。
C++不仅仅是 C 的超集(即增加多余的 C 特性)。在 C 和 C++中有少数特殊构造具有不同
的解释。而且有效的 C 代码可以包含一些在 C++中是保留字的标识符。基于这些原因,由 C
7