C 语言编码规范
众所周知,在制造业(尤其是汽车制造业)非常注重代码安全。MISRA-C 就是一个汽车制造业嵌入式 C 编码标准,最早由汽车工业软件可靠性联合会(Motor Industry Software Reliability Association,简称 MISRA)于 1998 年发布。2004 年发布了第二版的 MISRA C,即《MISRA-C-:2004 Guidelines for the use of the C language in critical systems》,是目前工业界常用的 C 语言编码规范。MISRA-C-:2004 规则分为 21 类,覆盖从「开发环境」到「运行期错误」,包含 141 项规则,其中 121 项是强制要求,其余的 20 项是推荐使用的规则。
本文以产品安全为目标,提炼部分 MISRA-C 语言的编码规范/编程规范,帮助提高企业级产品的代码可靠性、可读性和可移植性。
关键词 | 解释 |
---|---|
C 语言 | 一门面向过程、 抽象化的通用程序设计语言,广泛应用于底层开发。 |
MISRA-C | 汽车制造业嵌入式C编码标准。 |
1. 质量保证
软件工程师编码时,应该根据标准《MISRA-C-:2004》的规则进行编码,在设计过程中构筑软件质量。
1.1 代码质量保证优先原则
- 正确性,指程序要实现设计要求的功能。
- 稳定性、安全性,指程序稳定、可靠、安全。
- 可测试性,指程序要具有良好的可测试性。
- 规范/可读性,指程序书写风格、命名规则等要符合规范。
- 全局效率,指软件系统的整体效率。
- 局部效率,指某个模块/子模块/函数的本身效率。
- 个人表达方式/个人方便性,指个人编程习惯。
1.2 使用第三方提供的软件开发工具包或控件时,要注意以下几点:
- 充分了解应用接口、使用环境及使用时注意事项。
- 不能过分相信其正确性。
- 除非必要,不要使用不熟悉的第三方工具包与控件。
2. 代码编辑、编译、审查
- 打开编译器的所有告警开关对程序进行编译。
- 通过代码走读及审查方式对代码进行检查。
- 编写代码时要注意随时保存,并定期备份,防止由于断电、硬盘损坏等原因造成代码丢失。
- 同产品软件内,最好使用相同的编辑器,并使 用相同的设置选项。
- 合理地设计软件系统目录,方便开发人员使用。
- 某些语句经编译后产生告警,但如果你认为它是正确的,那么应通过某种手段去掉告警信息。
3. 代码测试、维护
- 单元测试要求至少达到语句覆盖。
- 单元测试开始要跟踪每一条语句,并观察数据流及变量的变化。
- 清理、整理或优化后的代码要经过审查及测试。
- 代码版本升级要经过严格测试。
- 使用工具软件对代码版本进行维护。
- 正式版本上软件的任何修改都应有详细的文档记录。
- 发现错误立即修改,并且要记录下来。
- 关键的代码在汇编级跟踪。
- 仔细设计并分析测试用例,使测试用例覆盖尽可能多的情况,以提高测试用例的效率。
- 尽可能模拟出程序的各种出错情况,对出错处理代码进行充分的测试。
- 仔细测试代码处理数据、变量的边界情况。
- 保留测试信息,以便分析、总结经验及进行更充分的测试。
- 不应通过“试”来解决问题,应寻找问题的根本原因。
- 对自动消失的错误进行分析,搞清楚错误是如何消失的。
- 修改错误不仅要治表,更要治本。
- 测试时应设法使很少发生的事件经常发生。
- 明确模块或函数处理哪些事件,并使它们经常发生。
- 坚持在编码阶段就对代码进行彻底的单元测试,不要等以后的测试工作来发现问题。
- 去除代码运行的随机性(如去掉无用的数据、代码及尽可能防止并注意函数中的“内部寄存器”等),让函数运行的结果可预测,并使出现的错误可再现。
4. 可测性
-
在同一项目组或产品组内,要有一套统一的为集成测试与系统联调准备的调测开关及相应打印函数,并且要有详细的说明。
-
在同一项目组或产品组内,调测打印出的信息串的格式要有统一的形式。信息串中至少要有所在模块名(或源文件名)及行号。
-
编程的同时要为单元测试选择恰当的测试点,并仔细构造测试代码、测试用例,同时给出明确的注释说明。测试代码部分应作为(模块中的)一个子模块,以方便测试代码在模块中的安装与拆卸(通过调测开关)。
-
在进行集成测试/系统联调之前,要构造好测试环境、测试项目及测试用例,同时仔细分析并优化测试用例,以提高测试效率。
-
在软件系统中设置与取消有关测试手段,不能对软件实现的功能等产生影响。
说明:即有测试代码的软件和关掉测试代码的软件,在功能行为上应一致。
-
用调测开关来切换软件的 DEBUG 版和正式版,而不要同时存在正式版本和 DEBUG 版本的不同源文件,以减少维护的难度。
-
软件的 DEBUG 版本和发行版本应该统一维护,不允许分家,并且要时刻注意保证两个版本在实现功能上的一致性。
-
在编写代码之前,应预先设计好程序调试与测试的方法和手段,并设计好各种调测开关及相应测试代码如打印函数等。