汽车工业软件可靠性协会(misra),是在英国政府的大力支持下,由多家汽车工业公司的代表组成,旨在规范汽车电子中软件的应用,并为嵌入式软件的发展提供指导意见。
汽车工业软件可靠性协会于1998年推出了一代misra c编码规范:misra c:1998,主要面向对代码可靠性有着强烈需求的领域。经过多年的发展,misra c已经从汽车行业编码规范发展成为跨行业的编码规范,成为世界范围内使用广泛的c语言编码规范。
2013年3月,汽车工业软件可靠性协会推出了第三代misra c编码规范:misra c:2012,本文将就这一新版本进行深入讨论。
引言
二十世纪九十年代,汽车电子产品的重要性日益凸显,汽车电子产品中的软件也随之变得举足轻重。人们迫切地需要一个编码规范来保证汽车电子软件的可靠性,在这一背景下,misra c编码规范应运而生。经过多年的发展,misra c已经成为世界范围内使用广泛的、面向多个行业的c语言编码规范。
汽车工业软件可靠性协会先后发布了三代misra c编码规范:
• 1998年,一代misra c编码规范:misra c:1998(mc1)
• 2004年,二代misra c编码规范:misra c:2004(mc2)
• 2013年,三代misra c编码规范:misra c:2012(mc3)
2013年3月18日,汽车工业软件可靠性协会发布了第三代misra c编码规范(mc3),无论您是否正在通过遵从misra c来开发代码,您的心中可能都会有如下的疑惑:
1.mc3真的有用么?
2.mc3真的比之前的两个版本好么?
3.通过遵从mc1或mc2开发出的代码,能够很好的遵从mc3么?
本文将就如上三个问题做出解答,同时本文还将向您展示:通过遵从mc3来开发代码,会为您带来什么。
不断演变的c语言
mc1和mc2都要求代码开发者遵守一代c语言标准:iso/iec 9899:1990——也就是被人们所熟知的c90。尽管c语言标准在不断地推陈出新,如1999年推出的c99及2011年推出的c11,misra c在很长一段时间内仍固守着一代c语言标准:c90——为什么?
至少有两个原因:
1.编译器供应商,尤其在嵌入式c语言领域,对新的c语言标准的响应速度很慢。如今,市面上的编译器普遍都能很好地支持c90。但对c99及c11的支持程度可谓千差万别。
2.尽管c语言不断地引入新的功能,但对于这些功能的可靠性,人们大都持着怀疑的态度,有些功能甚至可能引入了缺陷。
从标准化进程这一角度而言,c语言的标准是让人失望的:增加新的语言功能并非难事,但移除存在问题的语言功能却异常困难,因为移除语言功能极有可能影响到用户现有代码功能的实现。从某种意义上来讲,c语言本身的缺陷将长期存在,但编码规则的存在意义也正在于此:通过限制用户对特定c语言功能的使用,提高代码的可靠性。
可以预见的是,c语言仍会受到大众的追捧,并被广泛地应用于安全关键软件的开发之中。尽管mc3的开发人员对c99仍持保留态度,但在mc3的开发初期,开发人员就已决定不再拘泥于c90。c99的很多功能,如内联函数(inline function)、type_bool等,对于c语言而言已是非常重要的功能。不过mc3还是引入了11条规则,对c99某些功能的使用进行了限制。
mc3有哪些改变
精确的定义
清晰地为每个编码规则下一个定义——实际上,这项工作比想象中要难了许多,mc3的开发人员投入大量精力,对有可能产生歧义的定义进行修订。如今,每条定义都包含如下内容:
解释:阐述本编码规则的具体要求;
原理:解释本编码规则的必要性;
例外:列举不适用本编码规则的特殊情况;
举例:从代码遵从本编码规则和代码不遵从本编码规则两个角度进行举例。
必要的术语
当涉及技术性问题时,使用c语言的术语是很有必要的。这些术语符合iso c标准,对c语言给出了明确的定义。但是,当对编码规则进行定义的时候,我们有必要引入一些补充性质的“术语”。这一点,在c语言的“类型(type)”系统中显得尤为突出。
c语言的“类型”系统本身存在着很多不一致现象和异常。由该系统定义的算术表达式的类型看似很直观,但究其根本,这种定义方式却不能体现其本质。为此,mc2引入了基础类型(underlying type)和复杂表达式(complex expression)的概念。然而,现在看来,这两个定义的实际效果差强人意。
在misra c3中,基本类型(essential type)取代了基础类型(underlying type);复合表达式(composite expression)取代了复杂表达式(complex expression)。在定义编码规则时,基本类型以更为直观、更为有效的方式对算术表达式的类型进行描述,包含了完整的整数类型范围:
• 基本布尔类型
• 基本字符类型
• 基本枚举类型
• 基本signed类型
• 基本unsigned类型
• 基本浮点类型
强制性规则
mc1、mc2将编码规则分成两类:必要性规则(required rules)以及建议性规则(advisory rules)。声称符合misra c编码规范的代码,必须遵从所有必要性规则。对于建议性规则,代码开发人员则拥有更多的灵活性。
“这条编码规则是不是非常重要?”很多时候,这一判断是带有主观色彩的。在进行这一判断的过程中,您需要考虑很多因素,如:
1.如果我们违反了这条编码规则,软件出错的概率高么?
2.在开发过程中,违反这条编码规则的机会大么?
3.如果我们已经确定代码是安全的,这条编码规则是否还在不停的报错?
但是,有一些编码规则,无须任何主观判断,他们简单明了、毫无争议。mc3为他们创建了一个新的分组:强制性规则(mandatory rules)。在任何情况下,开发者都不可以违反强制性规则。
可执行性
汽车工业软件可靠性协会认为,静态代码检测工具在编码规则的执行过程中起着关键的作用。事实上,人们很早就认识到了编码规则自动执行的重要性:
1.消除不确定性;
2.节省时间;
3.在代码开发阶段提供实时信息反馈;
4.减少手动代码检查的工作量。
实际上,静态代码检测工具绝非一个简单的编码规则执行者,还能识别出编码规则以外的编码错误。
mc2中有9条编码规则,如果仅依靠源代码分析,是无法对这些编码规则进行合规性判定的,比如:
• 文档
• 过程要求
• 需求的松散定义
• 主观的评论意见
• 功能需求的理解
对于“不要使用逗号运算符”这样的编码规则,简单地对源代码进行分析即可进行合规性判定。但是对于下面的这些规则,仅通过源代码分析,是无法进行合规性判定的:
1.规则2.4:代码段不应被注释掉;
2.规则3.2:字符集和相应的编码应该文档化;
3.规则18.3:内存区域不能为不相关的目的而复用。
mc3指出了“规则”与“指令”之间的区别:
指令:仅仅依靠源代码分析,无法对“指令”进行合规性判定,往往需要开发人员提供更多的信息,如设计文档和要求说明。静态代码检测工具可以判定代码符合“指令”,但对于代码不符合“指令”的情况,静态代码检测工具给出的判定结果可能千差万别。
规则:仅仅依靠源代码分析,就可以对“规则”进行合规性判定,不需要开发人员提供更多的信息。所有的静态代码检测工具都应具对“规则”进行合规性判定的能力。
执行范围
编码规则执行的难易程度有着很大的差别。简单的规则(如“不得使用八进制常量”)可以通过简单的语句语法分析进行判定。然而,很多编码规则的判定,需要一条控制语句、一个完整的功能、一个完整的翻译单元、甚至一个项目的整个代码库的支撑才能进行判定。
在mc3中,每条编码规则都被划分为“系统规则”或“单一翻译单元规则”,用来反映编码规则的执行范围。这两者之间的区别如下:
1.单一翻译单元无法进行系统规则的合规性判定。
2.进行系统规则的合规性判定,往往意味着更高的要求及更多的时间。
可判定性
编码规则的另一个重要属性是可判定性。众所周知,编码规则的执行者——静态代码检测工具的能力差别很大。通过上文得知,对于一些简单的编码规则,只需进行简单的语法分析即可实现判定;而对于某些复杂的规则,则需要深入地分析代码的结构和语义。
对于一些编码规则,其本质是“不可判定的”——不论静态代码检测工具进行多么深入的分析,都无法判定代码的合规性;相反,当某个编码规则被违反,任何工具都可判定且不会误报,那么该规则被认为是“可判定的”。换句话说,任何工具对于“可判定的”编码规则,只会给出两个可能的答案:
1.yes – 此处违反该规则;
2.no –此处没有违反该规则;
mc3中,所有的规则都被划分为“可判定的”和“不可判定的”两类。共计143条编码规则,其中28条为“不可判定的”。当一个编码规则为“不可判定的”,那么对于这条规则,永远不能保证其合规性,工具可能会给出第三个答案:
3.无法保证合规性检查结果的准确性。
然而,我们发现,即使编码规则是可判定的,各种静态代码检测工具对编码规则的判定能力是参差不齐的。
差异
mc3对于那些遵循mc2开发的代码有何影响?mc3旨在解决与c99相关的新问题,其引入的新规则对于遵循mc2开发的代码的影响极为有限。
实际上,如果一个编码规则存在如下的问题,那么很难称其为好的编码规则。
1.不能准确判定已知的软件故障
2.允许代码存在规则中明令禁止的危险行为
3.对于未存在违反行为的代码有着诸多的限制
mc3对编码规则进行改进,重新编写了一部分规则,将少部分规则完全删除,解除了对编码的限制。
结论
mc3的文档看起来比mc2要大得多,但实际上,编码规则总数并没有增加多少:mc2包含了142条规则,而mc3包含了143条规则和16条指令。mc3在引入新规则的同时,修改了一些规则,也废除了一些规则。mc3的文档之所以大了许多,在于mc3的每条编码规则的体积都“变大”了:
1.更为精确的规则的描述——包括详细解释、基本原理、例外情况和示例;
2.增加了规则和指令的区别;
3.增加了系统规则和单一翻译单元规则之间的区别;
4.增加了可判定性的内容。
另外,对于哪些遵循mc2开发的代码,mc3对其造成的影响是极为有限的。
misra c致力于建立一个c语言安全子集,并通过静态代码检测工具自动执行,这使得misra编码规范拥有了大量的拥护者。支持misra c编码规则,已经成为众多静态代码检测工具及编译器的基本功能要求。
作者简介
paul burden—— prqa公司技术顾问。曾为全球客户提供培训和咨询服务,特别是编码标准的执行方面。在担任qa.c产品经理的几年里,在静态代码检测工具优缺点方面积累了丰富的经验。
prqa公司
prqa公司成立于1985年,被整个行业奉为“编程标准专家”。它是编码标准检验的先驱,并通过其业内先进的软件检验及标准执行技术向世界提供专业的服务。
prqa拥有业界先进的工具qa.c、qa.c 和qa.verify。这些工具拥有强大的、专有的解析能力,为c何c 代码提供完备实用的代码检查。它们通过对代码的分析,快速而精确的找出代码存在的诸多问题:如潜在的危险,代码过于复杂,不可移植或难以维护等一系列问题。另外,他们提供了一个编码标准的执行机制。
prqa提供专业的合规性模块来执行misra c:1998、misra c:2004、misra c:2012及misra c :2008。这些专业模块的效果得到了各行各业广泛的赞誉。详细情况可参看tera-labs(比利时安特卫普karel de grote 大学研究部门)提供的一个研究报告总结www.programmingresearch.com/resources/white-papers/(中文版可点击:http://www.hirain.com/?q=user-community/monthly/201212/use-cases/prqa)
prqa公司总部在英国,在美国,印度,爱尔兰和荷兰等多地都有代理商。详细情况可登陆prqa的官方网站:www.programmingresearch.com