MISRA C:2012 深度 — 基线 159 guidelines(143 Rule + 16 Directive)+ 3 级别 + ASIL D 强制 + Deviation 流程

功能安全L2别名 MISRA-C · MISRA C 2012 · coding standard ASIL D · Polyspace MISRA · 静态分析规则 · 更新

本质与导读

本质 MISRA C:2012 是 ISO 26262 对 ASIL C/D 落地「采用语言子集」的事实答案 —— 把 C 的 Undefined / Unspecified / Implementation-defined 行为与危险用法收进可静态判定的 subset。真正的工程约束在分级:Mandatory 绝对禁止 deviation;Required 违反必须文档化 justification + 独立评审 + 审批,并进安全案例的 deviation record;Advisory 可由项目在 Guideline Enforcement Plan(GEP)里选择采纳或重定级。基线 159 条(143 Rule + 16 Directive),经 Amendment 1/2 增补后维护版 175 条(16 Mandatory / 120 Required / 39 Advisory)

主线坐标:横轨 · 功能安全(跨站) · ↑ 全景主线

1. MISRA C:2012 全景

MISRA C 不是"风格建议",而是把一门定义了大量未定义行为的语言,裁成一个"每条违反都能被工具指出"的子集。下图把 3 级别 + 规则分组 + ASIL D 高频陷阱一次说清:

MISRA C:2012 — 基线 159 guidelines(143 Rule + 16 Directive),含 AMD1/2 共 175 + 3 级别 + ASIL D 强制

三个必须记牢的数字与观察:

  • 基线(2013)= 159 条 = 16 Directive + 143 Rule;其中约 10 条 Mandatory
  • 维护版(基线 + AMD1 2016 安全指南 + AMD2 2020 C11/C18)= 175 条,分级 16 Mandatory / 120 Required / 39 Advisory(数据取自工具分类矩阵,如 GrammaTech CodeSonar 7.3)
  • Mandatory 是唯一"绝不允许 deviation"的级别;工作量的绝大部分落在 Required,因为它才是"可 deviation 但必须走完整流程"的那一档

2. ISO 26262-6 与 MISRA 的关系

ISO 26262-6:2018 §5.4 Table 1「Topics to be covered by modelling and coding guidelines」是一张"编码/建模指南须覆盖哪些主题"的清单,每个主题按 ASIL 标 ++(highly recommended)/ +(recommended)/ o(no recommendation)。MISRA C 对应其中的「use of language subsets」这一主题——注意标准表只按 ASIL A-D 列,不含 QM(QM 无 ASIL 方法要求)。关键几行的分级如下(与本 wiki ISO 26262-6 软件页 Table 1 同源):

Table 1 主题ASIL AASIL BASIL CASIL D
Enforcement of low complexity++++++++
Use of language subsets(即 MISRA-C)++++++++
Enforcement of strong typing++++++++
Use of defensive implementation techniques++++++
Use of naming conventions++++++++

也就是说「使用语言子集」在 ASIL A 起就是 ++——它不是 ASIL D 才收紧,而是全等级 highly recommended。标准本身不点名 MISRA,但要求团队选一个"能被证明可降低 systematic fault 频率"的子集,MISRA C 是事实上的默认答案。FSAR / 功能安全评审拒签的 root cause 之一,就是 MISRA 不合规且 deviation 缺 justification。


3. 3 个 Category 详解

分级决定了"违反后要付出多少流程代价",这是理解 MISRA 落地成本的第一入口。除了级别,MISRA 还给每条标了两个正交属性:Decidable / Undecidable(工具能否静态判定,§6.5)与 Single Translation Unit / System(单文件可查还是需全局链接期分析,§6.4)——后者决定了增量式 CI 能否覆盖它。

3.1 Mandatory(基线约 10 条,维护版 16 条)

Mandatory 是"违反即错误、不接受任何理由"的一档,几乎都对准会直接导致 UB 或错误码丢失的构造:

  • 绝对禁止 deviation——工具报出即阻断集成,评审拒收
  • 维护版 16 条 Mandatory(均为 Rule,无 Mandatory Directive):9.1、12.5、13.6、17.3、17.4、17.6、19.1、21.13、21.17、21.18、21.19、21.20、22.2、22.4、22.5、22.6
  • 典型例:Rule 9.1(自动存储对象读取前必须已赋值,Undecidable)、Rule 17.4(有返回类型的函数所有退出路径都要 return)、Rule 22.2(不得 free 非动态分配或已释放的内存)
  • 注意:Rule 1.1(语法/约束/翻译限制)与 Rule 2.1(unreachable code)是 Required 而非 Mandatory——这是最常被误记的两条

3.2 Required(维护版 120 条)

Required 是工作量主体:允许违反,但每一处都要付"完整流程税"。

  • 违反需 deviation record:规则 ID + category + 原因 + 替代方案 + 风险评估 + 提出人/评审人/批准人
  • 覆盖高频陷阱区:Rule 11.x(pointer cast)、Rule 14.x/15.x(控制流)、Rule 21.3(malloc/free)、Rule 17.2(递归)
  • ASIL D 项目每条 Required deviation 必须可追溯并进安全案例

3.3 Advisory(维护版 39 条)

Advisory 是"建议",但在 ASIL D 项目里往往被 GEP 重定级(re-categorize)为 Required 后强制。

  • 项目可在 Guideline Enforcement Plan 里声明 "adopt all" / "selective" / 重定级
  • 典型例:Rule 17.8(函数参数不应被修改)、Rule 15.5(单一出口)、Rule 11.4(整数↔对象指针转换,寄存器访问高频命中,详见 §6)
  • Advisory 违反可不写 deviation——除非项目已把它升为 Required

4. 规则组织 — 16 Directive + 143 Rule(26 分组)

MISRA C:2012 把 guideline 组织成 4 组 Directive + 22 章 Rule(共 26 个分组)。Directive 与 Rule 的本质区别:Rule 只看 C 源码就能判定(可静态检查);Directive 关乎源码之外的信息(需求、编译配置、设计文档),工具只能部分辅助。

4.1 Directive(4 组,共 16 条)

Directive 管的是"代码之外"的合规,不能只靠 checker 全自动判定:

  • Dir 1 Implementation(Dir 1.1):把 target/编译器的 implementation-defined 行为记录并受控
  • Dir 2 Compilation and build(Dir 2.1):源文件应无编译错误(工程实务上加严为 warning=0)
  • Dir 3 Requirements traceability(Dir 3.1):所有代码可追溯到文档化需求(注意:这是需求追溯,不是覆盖率)
  • Dir 4 Code design(Dir 4.1–4.13):设计层约束,如 Dir 4.1(把运行时失败风险降到最小)、Dir 4.12(禁止动态内存分配)、Dir 4.7(检查函数的错误信息)。AMD1 增 Dir 4.14(校验外部来源数据),AMD3 增 Dir 4.15

4.2 Rule 1-10(语言基础 + 类型模型)

前十章收紧的是"语言 fundamentals"与 essential type model:

  • Rule 1-4:标准合规、编译期、字符集与注释
  • Rule 8 Declarations:声明/定义/链接一致性
  • Rule 9 Initialization:Rule 9.1 读前必写(Mandatory)
  • Rule 10 Essential type model:MISRA 自建的一套"本质类型"体系,收紧隐式类型转换与混合算术

4.3 Rule 11-15(指针 / 表达式 / 副作用 / 控制流)

中段是 ASIL D 最集中的陷阱区:

  • Rule 11 Pointer conversions:Rule 11.3(不同对齐类型间指针 cast,Required)、Rule 11.4(整数↔对象指针,Advisory)——寄存器访问高频
  • Rule 12 Expressions:Rule 12.1 显式括号、Rule 12.5(sizeof 操作数不得是数组形参,Mandatory)
  • Rule 13 Side effects:求值顺序与副作用,Rule 13.6(sizeof 操作数不得有副作用,Mandatory)
  • Rule 14-15 Control flow:循环/条件严格化,Rule 15.6 复合语句必加花括号

4.4 Rule 16-22(结构化 / 库 / 资源)

后段管结构化与库/资源使用:

  • Rule 16 Switch:Rule 16.4 每个 switch 必有 default、Rule 16.3 每个 clause 以无条件 break 收尾
  • Rule 17 Functions:Rule 17.2 禁递归(Required)Rule 17.4 所有退出路径 return(Mandatory)Rule 17.7 返回值不可弃(Required)
  • Rule 18 Pointers and arrays:Rule 18.1 指针算术不得越界
  • Rule 19 Overlapping storage:Rule 19.1 不得赋值/拷贝到重叠对象(Mandatory)
  • Rule 20 Preprocessor / Rule 21 Standard libraries:Rule 21.3 禁 malloc/freeRule 21.6 禁 <stdio.h>Rule 21.21 禁 system()(AMD2 新增)
  • Rule 22 Resources:Rule 22.1 动态获取的资源(文件/流)必须显式释放

5. ASIL D 主驱高频 MISRA 陷阱(5 类)

电驱控制器(EDU/主逆变器)ASIL D 软件里,以下 5 类违反出现频率最高,且都直接对应一个 systematic 失效模式。

5.1 Rule 11.x — pointer cast(寄存器访问)

访问 memory-mapped SFR 必然要把固定整数地址转成 volatile 指针,直接命中 Rule 11.4(整数↔对象指针,Advisory);跨对齐类型转换命中 Rule 11.3(Required)。工程做法:把 SFR 访问收敛到 vendor HAL/iLLD 一层,对 header 里那一处 cast 写集中 deviation,而不是让上层业务代码到处 cast(worked design 见 §6)。

5.2 Rule 21.3 / Dir 4.12 — 禁动态内存

ASIL D 主驱完全禁运行时动态内存:Rule 21.3 禁 malloc/free,Dir 4.12 从设计层禁"使用动态内存"。所有 buffer 编译期静态分配(static pool / 固定数组),因为堆碎片与分配失败在实时控制里不可接受、也无法给出 WCET 上界。

5.3 Rule 17.2 — 禁递归

Rule 17.2(Required)禁函数直接/间接调用自身,因为递归深度不可静态定界 → 栈用量不可控 → 潜在 stack overflow。主驱算法一律改循环/查表;栈用量再用工具(如 Polyspace / GHS)做静态栈深度分析佐证。

5.4 Rule 18.x — 数组越界

Rule 18.1 要求指针算术不越界。数组越界在有 ECC/SEU 背景的车规 MCU 上会放大成安全风险,故所有数组访问加边界检查,并用 Polyspace Code Prover(抽象解释,给出"证明无越界/证明越界/未证明"三态)做形式化佐证,而非仅靠 Bug Finder 的启发式扫描。

5.5 Rule 16.x — switch 必 default

Rule 16.4 要求每个 switch 有 default,Rule 16.3 要求每个 clause 无条件 break 收尾。状态机的 default 分支应落到 safe state(而非空 default),这样一个未预期的 enum 值就被引导到安全侧而不是 fall-through。


6. Worked design — AURIX TC375 SFR 访问触发 Rule 11.4 → deviation

把上面的 Rule 11.x 落到一颗真芯片上。Infineon AURIX TC375(TC3xx 家族,32-bit TriCore,带 lockstep core,ASIL-D ready)的 GPIO 端口是 memory-mapped SFR:Port P00 基址 0xF003A000,其中 OUT 寄存器在偏移 0x00(即 P00_OUT = 0xF003A000,见 AURIX TC3xx User Manual Part 2 · Ports 章)。要点亮一个接在 P00.0 的 LED,必须写这个物理地址——而"把整数地址当指针解引用"正是 Rule 11.4。

裸写法(违反且不可维护):

/* 直接把物理地址 cast 成 volatile 指针 —— 命中 Rule 11.4 (integer->object pointer) */
#define P00_OUT  (*(volatile uint32_t *)0xF003A000u)

void led_on(void)
{
    P00_OUT |= 0x1u;   /* 还顺带命中 Rule 10.x essential-type: 0x1u 与 uint32_t 混算 */
}

工程做法:把这唯一一处 cast 收敛进 vendor 层(AURIX iLLDMODULE_P00 宏本身就是 (*(Ifx_P *)0xF003A000u)),业务代码只调 IfxPort_setPinState(&MODULE_P00, 0, IfxPort_State_high),不再自己 cast。对 iLLD header 里那一处 cast 写一条集中 deviation:

/* deviation 锚点:寄存器基址必须由硬件手册固定,无法用 MISRA-conforming 写法表达 */
/* PRQA S 0303 1  // Helix QAC 抑制 Rule 11.4,关联 deviation record DVR-EDU-011 */
#define MODULE_P00  (*(Ifx_P *)0xF003A000u)

对应的 deviation record(MISRA Compliance:2020 字段):

字段内容
GuidelineRule 11.4(Advisory,项目 GEP 已升为 Required)
Scope仅 iLLD _Reg.h 内的 SFR 基址宏
Justification(category = Hardware)寄存器地址由芯片手册固定,不存在 MISRA-conforming 的等价写法;访问收敛到单层、加 volatile 防优化
Risk assessment无:地址来自 UM,编译期常量;不涉及运行时指针算术
Raised / Reviewed / ApprovedSW Eng / Safety Eng + Arch Lead / Safety Manager
TraceDVR-EDU-011 → 安全案例 deviation list → FSAR §5

这条 worked design 说明 MISRA 落地的核心不是"消灭所有违反",而是把不可避免的违反收敛到最小面、一次性论证、可追溯


7. Deviation 流程 + MISRA Compliance:2020

Deviation 不是"随手加个注释抑制告警",而是 MISRA Compliance:2020 定义的正式产物。每条 Required 违反走 5 步:

  1. 识别违反 — 静态分析工具输出(Polyspace / Helix QAC / LDRA)
  2. 写 deviation record — 规则 ID + category + justification + 替代方案 + 风险评估(字段见 §6)
  3. 独立评审 — Safety Engineer + Architecture Lead(maker≠checker,提出人不能自评)
  4. 批准 — Safety Manager 签字
  5. 记录与追溯 — Polarion / DOORS deviation list,安全案例与 FSAR 必引用

MISRA Compliance:2020 还定义了三个关键状态与两份产物,评审时常被查:

  • Compliant / Deviation / Disapplied:一条 guideline 要么合规,要么有已批准 deviation,要么在项目里被正式 disapplied(仅少数、需论证)
  • Guideline Enforcement Plan(GEP):声明每条 guideline 由哪个工具/复核环节强制,以及 Advisory 是否重定级
  • Guideline Compliance Summary(GCS):全项目逐条合规状态汇总,是"我们确实 MISRA 合规"的顶层证据

Justification 通常归 4 类:Hardware(寄存器访问)/ Performance(如 inline asm)/ Legacy/Third-party(既有库)/ Tool limitation(工具误报)。


8. Polyspace 工具链配置与 CI

Polyspace 是主驱线常见的 MISRA + 形式化组合(Bug Finder 快扫 + Code Prover 证明)。启用 MISRA C:2012 检查:

% Polyspace Bug Finder —— 启 MISRA C:2012 全集
proj = polyspace.Project;
proj.Configuration.CodingRulesCodeMetrics.EnableMisraC3 = true;
proj.Configuration.CodingRulesCodeMetrics.MisraC3Subset = 'all';   % all / mandatory-required / SQO-subset

报告与 CI 集成两点:

  • 报告:HTML/PDF 输出,按规则 + 文件分类;deviation 用源码内注释(polyspace-comment / PRQA S)锚定并关联 record ID
  • CI/CD:Jenkins / GitLab CI 每 PR 跑增量分析;Mandatory 违反直接 build fail,Required 违反除非有已批准 deviation 否则 fail;Advisory 按项目 GEP 决定阻断与否

9. LDRA vs Polyspace vs Coverity + 国产替代现状

主驱线常见三家工具各有定位。价格不公开(均为按 seat/项目谈判、六位数美元量级),故这里只比能力定位而不写虚假报价:

工具强项弱项典型定位
Polyspace(Bug Finder + Code Prover)抽象解释形式化证明(越界/溢出/除零三态)配置复杂、全量分析慢MBD + 手写混合,重形式化佐证
LDRA Testbed老牌、MISRA + 结构覆盖(含 MC/DC)一体、TCL 资料齐UI 陈旧传统 ECU、需一体化覆盖证据
Synopsys Coverity通用软件缺陷面广、扩展性好车规 MISRA 深度弱于前两者大型混合代码库的缺陷扫描

国产替代现状(去掉具体料号/报价以免误导):国产静态分析工具正在补 ISO 26262 工具链认证,但截至 2025 EV 主驱 ASIL D 仍以 Polyspace / LDRA / Coverity 为主。任何工具(含国产)进 ASIL D 工具链,都要先按 ISO 26262-8:2018 §11tool qualification(TCL 评估 + TVS/output comparison),否则其 MISRA 结论不能作为合规证据——这才是国产工具进主驱链的真正门槛,而非功能覆盖率。


10. ASIL D MISRA 合规验证清单

评审前对照这 5 项自查,任何一项缺失都是 FSAR 拒签风险:

  • Mandatory 100% 通过 — 零 violation,无 deviation 通道
  • Required 100% 处理 — 要么合规,要么有已批准 deviation record(含独立评审签字)
  • Advisory 按 GEP 处理 — 选择性采纳/重定级,决定写进 Guideline Enforcement Plan
  • Guideline Compliance Summary — 逐条状态汇总产物存在且与工具输出一致
  • 可追溯闭环 — deviation list → 安全案例 → FSAR §5 引用完整

11. 版本演进 — 2012(+AMD1-4)→ 2023 → 2025

MISRA C 的版本关系常被记乱,这里按事实澄清:

  • MISRA C:2012(2013):基线 159 条(143 Rule + 16 Directive)
  • + Amendment 1(2016):新增 14 条安全指南(13 Rule + Dir 4.14)→ 173 条
  • + Amendment 2(2020):支持 C11/C18 core(如新增 Rule 21.21 禁 system())→ 维护版约 175 条
  • + Amendment 3 / 4 + TC:补 C90/C99 遗漏与 concurrency(Dir 5.x)
  • MISRA C:2023(2023-04,第三版第二修订):把 AMD 与 TC 合并成一册,共 221 条(约 200 Rule + 21 Directive)——与本 wiki software-safety 页口径一致
  • MISRA C:2025(2025-03):在 2023 上做策略性增补,共 223 条(22 Mandatory / 153 Required / 47 Advisory / 1 Disapplied,新引入 Disapplied 第 4 态),仍面向 C99/C11/C18,为下一版 C 标准铺路

工程现实:2026 年在跑的 EV 主驱项目多数仍以 MISRA C:2012(含 AMD)为合规基线——因为工具链 qualification、既有 deviation 库、供应商约定都锚在 2012;向 2023/2025 迁移是有计划的动作,不是自动升级。且 ASIL D 主驱通常仍限 C99/C11 保守子集(编译器/工具对 C11 原子与线程支持不齐)。


12. Gotcha —— 7 个高频踩坑

以下 7 个是评审/交付阶段真正咬人的坑,多数不是"写错代码"而是"合规姿势错"。

  1. 把 Rule 1.1 / 2.1 当 Mandatory:二者其实是 Required。误记会让团队对真正的 16 条 Mandatory(9.1/17.4/22.2…)放松 —— 而 Mandatory 才是零容忍、无 deviation 通道的那档。
  2. 用注释抑制告警当成 deviationPRQA S / polyspace-comment 只是"抑制",不等于 deviation record。没有 justification + 独立评审签字 + 追溯,审计一律判 NCR(对齐 software-safety 页 G5)。
  3. Advisory 默认忽略:很多 Advisory 在 ASIL D 项目里已被 GEP 升为 Required(如 11.4)。不查 GEP 就按"Advisory 可不管"处理,交付时集中爆雷。
  4. Undecidable 规则指望工具 100% 查全:如 Rule 9.1(读前未写)是 Undecidable,静态工具只能保守报,漏报/误报都有;需靠设计约束 + 复核,不能把"工具没报"当"合规证明"。
  5. System 级规则漏在增量 CI:跨翻译单元的规则(Single Translation Unit vs System 属性)在只跑单文件增量分析时查不到,必须周期性跑全量链接期分析补齐。
  6. non-volatile 寄存器/双检被编译器优化掉:寄存器映射漏 volatile,或安全双重检查的中间变量非 volatile,被 CSE 合并——MISRA 不直接报,但破坏 safety 意图(与 software-safety 页 G2 同源)。
  7. essential type 混算悄悄改变符号/宽度:Rule 10.x 体系下,uint8_t 与带符号字面量混算会隐式提升,位运算结果符号位翻转;工具会报 10.x,但工程师常误 deviation 掉,埋下数值 bug。

13. Corner cases —— 3 个边界

三个"规则字面通过但工程语义存疑"的边界,评审时值得单独盯。

  • Disapplied 的滥用:MISRA Compliance:2020 允许把某条 guideline 在项目里正式 disapplied(如某平台确无该风险)。边界在于:disapplied 需与 deviation 同等论证并进 GCS,若被当"批量关规则"的捷径用,等于悄悄缩小了 subset——评审要核每条 disapplied 的理由。
  • 自动生成代码的类别切换:MISRA C:2012 Appendix E 指出,部分 guideline 对自动生成代码(Simulink/Embedded Coder + MISRA AC)的 category 与手写不同。混合工程里同一条规则在手写模块和生成模块判定级别不一致,合规矩阵必须分别标注,否则统计口径打架。
  • Mandatory 与硬件/编译器现实冲突:极少数情况下 Mandatory 的字面要求与某 target 的必要写法冲突(如特殊 startup 代码)。因为 Mandatory 无 deviation 通道,唯一合规出路是把该片段隔离到非 MISRA 声明的边界(如汇编/受控封装)并在 Dir 1.1 记录,而不是硬写 deviation——写了也不被接受。

14. 一句话总结

MISRA C:2012 = ASIL D 软件强制门票 — 基线 159 条(143 Rule + 16 Directive),含 AMD1/2 维护版 175 条,分级 16 Mandatory(绝不 deviation)/ 120 Required(须完整 deviation 流程)/ 39 Advisory(GEP 可重定级)。ISO 26262-6 Table 1「use of language subsets」在 ASIL A-D 全 ++5 大陷阱:Rule 11.x cast(寄存器,见 AURIX TC375 worked design)/ Rule 21.3+Dir 4.12 动态内存 / Rule 17.2 递归 / Rule 18.1 越界 / Rule 16.4 switch default。主流工具 Polyspace(Bug Finder + Code Prover)/ LDRA / Coverity + CI 阻断 + deviation record(MISRA Compliance:2020)闭环 → FSAR §5。别记错:Rule 1.1/2.1 是 Required 不是 Mandatory;下一版是 MISRA C:2023(221)/ 2025(223) 而非"2025 加 C11"。


核心要点

  • MISRA C:2012 = ISO 26262-6 Table 1「use of language subsets」的事实答案,ASIL A-D 全 ++(不是 D 才收紧)
  • 基线 159 条(143 Rule + 16 Directive);含 AMD1/2 维护版 175 条 = 16 Mandatory / 120 Required / 39 Advisory
  • Mandatory 零 deviation(9.1/17.4/22.2…);Rule 1.1/2.1 是 Required,常被误记为 Mandatory
  • Directive 关乎代码之外(需求追溯/编译配置),Rule 只看源码;Directive 共 16 条(Dir 1.1/2.1/3.1/4.1–4.13)
  • Deviation = 正式 record(justification + 独立评审 + 追溯),不是抑制注释;闭环进 FSAR §5
  • 版本:2012(+AMD1-4)→ MISRA C:2023(221)→ MISRA C:2025(223, 新增 Disapplied 态)

缩写表

只列本页用到的工业标准缩写;通用英语…

只列本页用到的工业标准缩写;通用英语 / 单位 / 月份 / 我们的 层/Lx tag 不列。覆盖不到的术语见正文 inline 注释。

缩写全称中文 / 备注
ASILAutomotive Safety Integrity LevelISO 26262 安全完整性等级 QM→A→B→C→D
ISOInternational Organization for Standardization国际标准化组织
UBUndefined BehaviorC 标准未定义行为
SFRSpecial Function Register片上外设的 memory-mapped 寄存器
iLLDinfineon Low Level DriverAURIX 官方底层驱动库
GEPGuideline Enforcement PlanMISRA 合规:声明每条如何强制/重定级
GCSGuideline Compliance SummaryMISRA 合规:逐条状态汇总产物
FSARFunctional Safety Assessment Report功能安全评估报告
MC/DCModified Condition/Decision Coverage修正条件/判定覆盖
TCLTool Confidence LevelISO 26262-8 工具置信度等级

Cross-references