规则分类总览:规则编号体系、分组与优先级矩阵

各位同学,欢迎来到第三章。这一章我们不讲具体代码,而是先把MISRA C的规则体系这张地图摊开。我个人习惯是,学任何标准前,先搞清楚它的骨架。你想想看,如果连规则怎么编号、分几类、哪些是红线都不知道,后面排查问题就像没头苍蝇。

MISRA C的规则体系,说白了就是三件事:编号怎么认、规则怎么分组、优先级怎么定。搞懂这三样,你拿到任何一条规则,扫一眼编号就知道它属于哪类、严不严重。

3.1 规则编号体系:Dir与Rule

MISRA C的规则编号分两大类:指令(Directive)和规则(Rule)。我刚开始接触时也纳闷,为什么搞两套?后来踩了坑才明白——这是为了区分“必须做”和“怎么做”。

类型 前缀 含义 可验证性 举例
指令 Dir 设计层面的要求,描述“应该做什么” 通常无法静态检查,需要人工评审 Dir 4.1:运行期行为必须可预测
规则 Rule 编码层面的约束,描述“不能怎么写” 通常可被静态分析工具自动检查 Rule 10.1:操作数不能有不合法的基本类型
我的经验:Dir类规则容易被团队忽略,因为工具抓不出来。我曾经在一个项目中,Dir 4.1(运行期行为可预测)被大家当成“软要求”,结果在中断嵌套场景下出了时序问题。记住:Dir是设计契约,评审时必须逐条过。

编号格式上,Dir和Rule都采用“大类.序号”的方式。比如Rule 10.1,10是类型转换大类,1是该大类下的第一条规则。这种设计让你一眼就知道规则归属哪个主题域。

3.2 规则分组:三个层面

MISRA C 2012把规则分成三大组。我把它总结为“语言层面、编程实践、文档要求”。这三层从语法到习惯到管理,层层递进。

3.2.1 语言层面(Language Level)

这部分规则直接约束C语言的语法和语义。说白了,就是告诉你“C语言这个特性别乱用”。比如:

  • 类型转换(Rule 10.x系列):隐式转换、整型提升、指针转换
  • 表达式(Rule 12.x系列):副作用、求值顺序、运算符优先级
  • 控制流(Rule 14.x系列):if-else配对、switch穿透、循环终止
避坑指南:我曾经在评审代码时,发现有人用 if (a = b) 做赋值判断。Rule 13.2明确禁止这种“赋值作为布尔值”的写法。工具能扫出来,但前提是你开了这条规则。

3.2.2 编程实践(Programming Practice)

这一层更偏向“怎么写代码更安全”。它不直接说语法错误,而是约束编码习惯。比如:

  • 命名与注释(Dir 4.x系列):标识符不能重复、注释不能嵌套
  • 函数设计(Rule 8.x系列):函数参数个数限制、返回值必须使用
  • 内存管理(Rule 22.x系列):动态内存分配限制、指针使用规范

我个人觉得,编程实践类规则是团队最容易“讨价还价”的地方。比如Rule 8.2要求函数参数不超过6个,有人觉得太死板。但我在一个通信协议栈项目里,见过一个函数有12个参数,调试时根本记不清顺序——后来重构时拆成3个结构体,bug率直接降了一半。

3.2.3 文档要求(Documentation Requirement)

这类规则不直接管代码,而是管“你写代码时留下的记录”。比如:

  • 偏差记录(Dir 4.12):如果违反某条规则,必须记录理由和审批
  • 工具配置(Dir 4.13):静态分析工具的配置必须文档化
  • 编译器行为(Dir 4.14):依赖编译器特定扩展时必须说明
注意:文档要求类规则在合规审计时是重点。我见过一个团队代码写得很好,但偏差记录不全,审计直接被判“不合规”。别以为代码干净就够了,纸面功夫也得跟上。

3.3 规则优先级与严重性矩阵

MISRA C把每条规则按“必须遵守”和分了两个层级。但实际项目中,我更喜欢用“严重性 × 可能性”矩阵来排优先级。下面这张表是我自己整理的,供你参考:

优先级 严重性 违反后果 典型规则举例 我的建议
P0(致命) 高 可能导致系统崩溃、安全失效 Rule 1.3(未定义行为)、Rule 18.1(指针算术越界) 零容忍,工具必须阻断编译
P1(严重) 高 可能导致数据损坏、逻辑错误 Rule 10.1(非法类型转换)、Rule 13.2(赋值当布尔) 必须修复,评审重点
P2(中等) 中 可能导致可维护性下降、偶发bug Rule 8.2(参数过多)、Rule 15.5(switch无default) 建议修复,可申请偏差
P3(低) 低 风格问题,不影响功能 Rule 4.1(八进制常量)、Rule 5.1(标识符长度) 团队约定即可,审计时说明
实战技巧:我在做合规整改时,会先扫一遍P0和P1的规则。通常这两类能覆盖80%的严重问题。P2和P3的规则,我会结合项目风险等级来决定是否全部启用。比如安全完整性等级SIL3的项目,P2也得全开。

3.4 知识体系总览图

下面这张SVG图,把规则分类的整个骨架画出来了。你可以把它当成“MISRA C规则地图”贴在工位上。

MISRA C规则分类总览 MISRA C 规则分类总览 指令 (Directive) 规则 (Rule) 语言层面 编程实践 文档要求 类型转换 (Rule 10.x) 表达式 (Rule 12.x) 控制流 (Rule 14.x) 命名与注释 (Dir 4.x) 函数设计 (Rule 8.x) 内存管理 (Rule 22.x) 偏差记录 (Dir 4.12) 工具配置 (Dir 4.13) 编译器行为 (Dir 4.14) 优先级矩阵:P0(致命) → P1(严重) → P2(中等) → P3(低) P0/P1:零容忍,工具阻断编译 P2/P3:建议修复,可申请偏差

3.5 如何用这套体系做合规整改

有了上面的地图,你拿到一份代码后,可以按这个步骤来:

  1. 先扫P0/P1的Rule:用静态分析工具(比如PC-lint、Coverity)跑一遍,把致命和严重问题全部列出来。
  2. 再查Dir类指令:人工评审设计文档和代码,看有没有违反Dir 4.1(可预测性)、Dir 4.12(偏差记录)等。
  3. 最后过P2/P3:根据项目安全等级决定是否全部整改。如果时间紧,可以申请偏差,但必须记录理由。
踩坑提醒:我曾经在一个项目里,团队只关注了Rule类规则,觉得Dir类“反正工具查不出来”就放过了。结果审计时,审计师拿着Dir 4.12一条条对偏差记录,我们当场傻眼——有3处违反没写偏差说明。后来补了整整两天文档。记住:审计看的是“你有没有做”,不是“工具能不能查”。