MISRA C++:2008 完整分析报告
文档名称 : MISRA C++:2008 --- Guidelines for the use of the C++ language in critical systems
发布机构 : The Motor Industry Software Reliability Association (MISRA)
版本 : 2008 年 6 月第一版
页数 : 220 页
ISBN : 978-1-906400-03-3 (纸质版) / 978-1-906400-04-0 (PDF 版)
适用对象 : 汽车、嵌入式、安全关键系统的 C++ 软件开发
C++ 标准: ISO/IEC 14882:2003 (C++03)
一、规则统计概览
| 总数 | Required (强制) | Advisory (建议) | Document (文档要求) |
|---|---|---|---|
| 226 | 198 (87.6%) | 16 (7.1%) | 12 (5.3%) |
二、章节结构总览
| 章号 | 主题 | 规则数 | Required | Advisory | Document |
|---|---|---|---|---|---|
| 0 | 语言无关问题 / Language Independent Issues | 18 | 14 | 0 | 4 |
| 1 | 语言标准合规 / Language Standard Compliance | 3 | 1 | 0 | 2 |
| 2 | 词法 / Lexical Issues | 17 | 13 | 3 | 1 |
| 3 | 声明与定义 / Declarations & Definitions | 13 | 12 | 1 | 0 |
| 4 | 初始化 / Initialization | 5 | 5 | 0 | 0 |
| 5 | 表达式 / Expressions | 41 | 36 | 5 | 0 |
| 6 | 语句 / Statements | 23 | 23 | 0 | 0 |
| 7 | 类与派生 / Class & Derived Classes | 16 | 14 | 1 | 1 |
| 8 | 模板 / Templates | 9 | 9 | 0 | 0 |
| 9 | 异常与特殊函数 / Exception & Special Functions | 8 | 7 | 0 | 1 |
| 10 | 环境 / Environment | 6 | 4 | 2 | 0 |
| 11 | 位字段 / Bit-fields | 1 | 1 | 0 | 0 |
| 12 | 派生类/构造析构 / Derived Classes | 5 | 4 | 1 | 0 |
| 14 | 重载 / Overloading | 10 | 9 | 1 | 0 |
| 15 | 库(通用) / Libraries (general) | 17 | 14 | 2 | 1 |
| 16 | 标准库 / Standard Library | 19 | 16 | 2 | 1 |
| 17 | 输入输出 / Input/Output | 5 | 4 | 0 | 1 |
| 18 | 动态内存 / Dynamic Memory | 8 | 8 | 0 | 0 |
| 19 | 预处理 / Preprocessing | 1 | 1 | 0 | 0 |
| 27 | 杂项 / Miscellaneous | 1 | 1 | 0 | 0 |
三、按主题分类的核心规则
3.1 对功能安全最关键的高频违规规则(TOP 15)
| 优先级 | 规则 | 级别 | 内容简述 |
|---|---|---|---|
| ⭐⭐⭐ | Rule 18--4--01 | Required | 动态堆内存分配禁止 --- new/delete、malloc/free 全部禁止 |
| ⭐⭐⭐ | Rule 18--0--01 | Required | C 标准库 (<stdlib.h>, <string.h>, <stdio.h> 等) 禁止使用 |
| ⭐⭐⭐ | Rule 5--2--04 | Required | C-style cast 禁止,必须使用 C++ cast |
| ⭐⭐⭐ | Rule 5--2--06 | Required | 函数指针不可转换为其他指针类型 |
| ⭐⭐⭐ | Rule 5--2--07 | Required | 无关指针类型之间不可转换 |
| ⭐⭐⭐ | Rule 5--2--08 | Required | 整数/枚举不可转换为指针 |
| ⭐⭐⭐ | Rule 5--2--05 | Required | const_cast 禁止 |
| ⭐⭐⭐ | Rule 5--0--19 | Required | 指针间接级别不超过 2 级 |
| ⭐⭐⭐ | Rule 7--5--04 | Advisory | 递归禁止(直接或间接) |
| ⭐⭐⭐ | Rule 6--6--05 | Required | 函数单出口原则 |
| ⭐⭐⭐ | Rule 6--4--05 | Required | switch 每个 case 必须有 break |
| ⭐⭐⭐ | Rule 6--4--06 | Required | switch 必须有 default |
| ⭐⭐⭐ | Rule 0--1--09 | Required | 禁止死代码(Dead Code) |
| ⭐⭐⭐ | Rule 0--1--01 | Required | 禁止不可达代码(Unreachable Code) |
| ⭐⭐⭐ | Rule 7--5--01 | Required | 函数不可返回局部变量的引用或指针 |
3.2 类型安全规则
| 规则 | 级别 | 内容 |
|---|---|---|
| Rule 5--0--03 | Required | 表达式不可隐式转换为不同类型 |
| Rule 5--0--04 | Required | 隐式整数转换不改变 signedness |
| Rule 5--0--05 | Required | 浮点到整数的隐式转换禁止 |
| Rule 5--0--06 | Required | 隐式转换不减小类型大小 |
| Rule 5--0--07 ~ 5--0--09 | Required | 显式 cast 不改变 signedness |
| Rule 5--0--12 | Required | signed char 和 unsigned char 仅用于数值存储 |
| Rule 3--9--01 | Required | 跨编译单元类型须 token-for-token 一致 |
3.3 表达式与控制流
| 规则 | 级别 | 内容 |
|---|---|---|
| Rule 6--2--01 | Required | 赋值运算符不可用于子表达式 |
| Rule 6--3--01 | Required | if/while/for 体须为复合语句 { } |
| Rule 6--4--03 | Required | switch 须符合规范语法 |
| Rule 6--4--04 | Required | switch 中禁止 return/break 以外的跳转 |
| Rule 6--5--01 | Required | for 循环须有且仅有一个循环计数器 |
| Rule 5--0--15 | Required | 指针算术仅限数组索引形式 |
| Rule 5--0--16 | Required | 指针算术不超出数组边界 |
3.4 异常处理
| 规则 | 级别 | 内容 |
|---|---|---|
| Rule 15--0--01 | Document | 异常仅用于错误处理 |
| Rule 15--0--03 | Required | 不可将控制转入 try/catch 块 |
| Rule 15--1--02 | Required | 禁止抛出 (...) 空异常 |
| Rule 15--3--05 | Required | 类类型异常必须按引用捕获 |
| Rule 15--5--01 | Required | 析构函数不可因异常退出 |
3.5 预处理
| 规则 | 级别 | 内容 |
|---|---|---|
| Rule 16--0--01 | Required | #include 后只允许预处理指令或注释 |
| Rule 16--0--03 | Required | 使用 #ifndef / #define / #endif include guard |
| Rule 16--0--04 | Required | 函数宏由函数替代 |
| Rule 16--2--01 | Required | 优先使用 const/inline/template 替代宏 |
| Rule 16--2--02 | Required | C++ 宏仅用于 include guard 和条件编译 |
| Rule 16--2--03 | Required | 所有头文件须有唯一 include guard |
3.6 命名规范
| 规则 | 级别 | 内容 |
|---|---|---|
| Rule 2--10--01 | Required | 避免视觉混淆的标识符 |
| Rule 2--10--02 | Required | 内部作用域不可隐藏外部名称 |
| Rule 2--10--03 | Required | 同一作用域名称不可复用 |
四、完整规则列表(按章节)
第 0 章: 语言无关问题(18 条规则)
| 规则编号 | 类型 | 规则说明 |
|---|---|---|
| Rule 0--1--01 | Required | 不可存在不可达代码(编译器可不为之生成代码) |
| Rule 0--1--02 | Required | 不可存在不可行路径(语法存在但语义保证控制不会到达的路径) |
| Rule 0--1--03 | Required | 已声明但从未使用的变量属于噪音代码,须移除 |
| Rule 0--1--04 | Required | 除 volatile 变量外,声明但仅使用一次的变量无意义 |
| Rule 0--1--05 | Required | 声明但未使用的类型应移除或使用 |
| Rule 0--1--06 | Required | volatile 变量赋值后从未读取属于无用写入(Dead Store) |
| Rule 0--1--07 | Required | 有非 void 返回类型的函数(非重载运算符)返回值必须被使用 |
| Rule 0--1--08 | Required | void 返回类型的函数必须有外部副作用 |
| Rule 0--1--09 | Required | 禁止死代码(删除后不影响输出的可执行语句) |
| Rule 0--1--10 | Required | 从未被调用的函数应移除 |
| Rule 0--1--11 | Required | 禁止未使用的命名参数 |
| Rule 0--1--12 | Required | 禁止未使用的未命名参数(虚函数参数除外) |
| Rule 0--2--01 | Required | 对象不可赋值给重叠对象(overlapping storage) |
| Rule 0--3--01 | Document | 须注意最小化运行时错误(C++语言自身防护较弱) |
| Rule 0--3--02 | Required | 函数产生错误信息后必须测试这些错误信息 |
| Rule 0--4--01 | Document | 若使用运行时错误检查则须文档化 |
| Rule 0--4--02 | Document | 须深入了解编译器和目标硬件特性并文档化 |
| Rule 0--4--03 | Document | 浮点实现须符合标准浮点规范并文档化 |
第 1 章: 语言标准合规(3 条规则)
| 规则编号 | 类型 | 规则说明 |
|---|---|---|
| Rule 1--0--01 | Required | 所有代码须符合 ISO/IEC 14882:2003 |
| Rule 1--0--02 | Document | 若使用多编译器,须确认各编译器行为一致并文档化 |
| Rule 1--0--03 | Document | 整型除法行为须确定并文档化 |
第 2 章: 词法问题(17 条规则)
| 规则编号 | 类型 | 规则说明 |
|---|---|---|
| Rule 2--2--01 | Document | 字符集及对应编码须文档化 |
| Rule 2--3--01 | Required | 禁止使用三字符组(Trigraphs) |
| Rule 2--5--01 | Advisory | 避免使用 digraph 替代符 |
| Rule 2--7--01 | Required | C 风格注释不支持嵌套,禁止依赖嵌套注释 |
| Rule 2--7--02 | Required | 禁止用 C 风格注释 /* */ 来"注释掉"代码段 |
| Rule 2--7--03 | Advisory | 建议也不要用 C++ 风格注释 // 来注释掉代码 |
| Rule 2--10--01 | Required | 避免视觉上易混淆的标识符 |
| Rule 2--10--02 | Required | 内层作用域不可隐藏外层作用域名称 |
| Rule 2--10--03 | Required | 同一作用域不可复用名称 |
| Rule 2--10--04 | Required | 同一作用域不可复用类型名或名称空间名 |
| Rule 2--10--05 | Advisory | 静态存储期名称不应跨作用域复用 |
| Rule 2--10--06 | Required | 同一作用域中类型名和变量/函数名不可相同 |
| Rule 2--13--01 | Required | 字符常量中禁止使用八进制转义序列外的 \ 序列 |
| Rule 2--13--02 | Required | 禁止八进制常量(零除外) |
| Rule 2--13--03 | Required | 0x 前缀十六进制字面量须使用无符号后缀 |
| Rule 2--13--04 | Required | 字面量后缀须使用大写(U、L 而非 u、l) |
| Rule 2--13--05 | Required | 窄字符串和宽字符串不可拼接 |
第 3 章: 声明与定义(13 条规则)
| 规则编号 | 类型 | 规则说明 |
|---|---|---|
| Rule 3--1--01 | Required | 头文件须用于声明对象、函数、模板等 |
| Rule 3--1--02 | Required | 禁止在块作用域内声明函数 |
| Rule 3--1--03 | Required | 数组声明须指定大小或提供初始化器 |
| Rule 3--2--01 | Required | 对象/函数的所有声明须兼容 |
| Rule 3--2--02 | Required | 单一定义规则(ODR)不得违反 |
| Rule 3--2--03 | Required | 多文件使用的类型/对象/函数须有单一声明 |
| Rule 3--2--04 | Required | 不同翻译单元的相同标识符类型声明须 token 序列一致 |
| Rule 3--3--01 | Required | 外部链接对象/函数须在头文件中声明 |
| Rule 3--3--02 | Required | 内部链接函数的所有重声明须包含 static |
| Rule 3--4--01 | Required | 全局对象须在多个翻译单元中使用 |
| Rule 3--9--01 | Required | 类型、函数返回类型、参数类型在所有声明中须 token-for-token 一致 |
| Rule 3--9--02 | Advisory | 建议使用显式大小类型而非 short/long/double |
| Rule 3--9--03 | Required | 应使用 typedef 定义显式大小类型 |
第 4 章: 初始化(5 条规则)
| 规则编号 | 类型 | 规则说明 |
|---|---|---|
| Rule 4--5--01 | Required | bool 表达式不可用于内建运算符(赋值、取地址、逗号、条件运算符除外) |
| Rule 4--5--02 | Required | bool 表达式不可用于内建运算符(下标、赋值、取地址、逗号、条件除外) |
| Rule 4--5--03 | Required | enum 类型不可用于内建运算符(赋值、取地址、逗号、条件除外) |
| Rule 4--10--01 | Required | 字面量 0 不可用作空指针常量(应使用 NULL 宏) |
| Rule 4--10--02 | Required | 字面零(0)须用于算术或初始化,空指针用 NULL |
第 5 章: 表达式(41 条规则 --- 最密集章节)
| 规则编号 | 类型 | 规则说明 |
|---|---|---|
| Rule 5--0--01 | Required | 表达式的值在任何求值顺序下须相同 |
| Rule 5--0--02 | Advisory | 不应依赖 C++ 运算符优先级规则 |
| Rule 5--0--03 | Required | cvalue 表达式不可隐式转换为不同类型 |
| Rule 5--0--04 | Required | 隐式整数转换不得改变 signedness |
| Rule 5--0--05 | Required | 禁止浮点到整数的隐式转换 |
| Rule 5--0--06 | Required | 隐式转换不得减小类型大小 |
| Rule 5--0--07 | Required | 显式转换不得用于改变类型的 signedness |
| Rule 5--0--08 | Required | 显式转换不得用于增大类型大小 |
| Rule 5--0--09 | Required | 显式整数转换不得改变 signedness |
| Rule 5--0--10 | Required | 位运算符应用于 signed 或 unsigned 类型后须立即强制转型 |
| Rule 5--0--11 | Required | char 类型仅用于字符存储和使用 |
| Rule 5--0--12 | Required | signed char 和 unsigned char 仅用于数值存储 |
| Rule 5--0--13 | Required | 条件运算符中非 bool 类型的条件值须显式转换 |
| Rule 5--0--15 | Required | 指针算术仅限于数组索引形式 |
| Rule 5--0--16 | Required | 指针运算须在同一数组内 |
| Rule 5--0--17 | Required | 指针减法仅限于同一数组的元素 |
| Rule 5--0--18 | Required | > / < / >= / <= 比较仅限于指向同一数组的指针 |
| Rule 5--0--19 | Required | 指针间接级别不超过 2 级 |
| Rule 5--0--20 | Required | 二元位运算符的操作数须为相同底层类型 |
| Rule 5--0--21 | Required | 位运算符仅用于无符号操作数 |
| Rule 5--2--01 | Required | 逻辑 &&/` |
| Rule 5--2--02 | Required | 指向虚基类的指针仅可通过 dynamic_cast 转换 |
| Rule 5--2--03 | Advisory | 基类到派生类的向下转型不应通过 C-style cast 进行 |
| Rule 5--2--04 | Required | C 风格 cast 禁止 (应使用 C++ 的 static_cast/dynamic_cast/reinterpret_cast) |
| Rule 5--2--05 | Required | 禁止通过 cast 移除 const 或 volatile (const_cast 禁止) |
| Rule 5--2--06 | Required | 函数指针不可转换为其他指针类型 |
| Rule 5--2--07 | Required | 对象指针不可转换为无关的指针类型 |
| Rule 5--2--08 | Required | 整数或枚举类型不可转换为指针类型 |
| Rule 5--2--09 | Advisory | 指针类型不应转换为整型 |
| Rule 5--2--10 | Advisory | 自增/自减运算符不应与其他运算符混用 |
| Rule 5--2--11 | Required | 逗号运算符和 &&/` |
| Rule 5--2--12 | Required | 数组作为函数实参时类型衰退到指针须注意 |
| Rule 5--3--01 | Required | && / ` |
| Rule 5--3--02 | Required | 一元减号不可用于无符号表达式 |
| Rule 5--3--03 | Required | & 运算符不可重载 |
| Rule 5--3--04 | Required | sizeof 的操作数须为完整类型 |
| Rule 5--8--01 | Required | 移位运算符的右操作数须在 [0, 类型位宽) 区间内 |
| Rule 5--14--01 | Required | 逻辑 && / ` |
| Rule 5--17--01 | Required | 二元运算符与其赋值运算符形式须保持语义等价 |
| Rule 5--18--01 | Required | 禁止使用逗号运算符 (,) |
| Rule 5--19--01 | Advisory | 无符号常量表达式求值不应发生回绕 |
第 6 章: 语句(23 条规则)
| 规则编号 | 类型 | 规则说明 |
|---|---|---|
| Rule 6--2--01 | Required | 赋值运算符不可用于子表达式 |
| Rule 6--2--02 | Required | 浮点表达式不可直接或间接测试相等/不等 |
| Rule 6--2--03 | Required | 空语句(null statement)仅允许出现在空行(预处理前) |
| Rule 6--3--01 | Required | if / while / for / do 的循环体须为复合语句 { } |
| Rule 6--4--01 | Required | if-else if 链的尾部 else 须为复合语句或另一 else if |
| Rule 6--4--02 | Required | if-else if 链的尾部须有 else |
| Rule 6--4--03 | Required | switch 语句须符合规范语法 |
| Rule 6--4--04 | Required | switch 语句 case 标签后仅允许 break / return 结束(禁止 fall-through) |
| Rule 6--4--05 | Required | switch 每个非空 case 须以无条件 break 结束 |
| Rule 6--4--06 | Required | switch 必须有 default 子句 |
| Rule 6--4--07 | Required | switch 的条件表达式须为整型或枚举型 |
| Rule 6--4--08 | Required | switch 的每个 case 须是常量表达式 |
| Rule 6--5--01 | Required | for 循环须有且仅有一个循环计数器 |
| Rule 6--5--02 | Required | 若使用 for / while / do,不能使用 break / goto 提前退出 |
| Rule 6--5--03 | Required | for 循环的循环体不能修改循环计数器 |
| Rule 6--5--04 | Required | for / while / do 的循环终止条件须为可在编译期确定的循环边界 |
| Rule 6--5--05 | Required | 循环体内部不可修改循环计数器 |
| Rule 6--5--06 | Required | 循环体内部仅循环计数器可用于循环终止条件 |
| Rule 6--6--01 | Required | goto 指向的标签须在同一块或外层块中声明 |
| Rule 6--6--02 | Required | goto 须跳转到同一函数后面声明的标签 |
| Rule 6--6--03 | Required | goto 语句应仅用于错误处理 |
| Rule 6--6--04 | Required | 迭代语句中最多一个 break 或 return 用于循环终止 |
| Rule 6--6--05 | Required | 函数须有单一出口(末尾处) |
第 7 章: 类与派生(16 条规则)
| 规则编号 | 类型 | 规则说明 |
|---|---|---|
| Rule 7--1--01 | Required | 类成员数据不可为 public |
| Rule 7--1--02 | Required | 指针或引用参数若不修改指向对象须声明为 const |
| Rule 7--2--01 | Required | 枚举表达式须有对应的枚举值 |
| Rule 7--3--01 | Required | 全局命名空间应仅包含 main、operator new/delete 等 |
| Rule 7--3--02 | Required | using 声明用于函数时仅限全局命名空间的函数 |
| Rule 7--3--03 | Required | 禁止匿名命名空间(unnamed namespace) |
| Rule 7--3--04 | Required | 头文件中禁止 using-directive(using namespace) |
| Rule 7--3--05 | Required | 名称空间定义中禁止 using-directive |
| Rule 7--3--06 | Required | 头文件/源文件不可使用 using-directive |
| Rule 7--4--01 | Document | 所有汇编使用须文档化 |
| Rule 7--4--02 | Required | 汇编指令仅可通过 asm 声明引入 |
| Rule 7--4--03 | Required | 汇编语言须封装和隔离 |
| Rule 7--5--01 | Required | 函数不可返回局部变量的引用或指针 |
| Rule 7--5--02 | Required | 自动存储对象的地址不可赋值给可能持久化的对象 |
| Rule 7--5--03 | Required | 函数不可返回对引用参数的指针或引用 |
| Rule 7--5--04 | Advisory | 函数不应直接或间接调用自身(递归) |
第 8 章: 模板(9 条规则)
| 规则编号 | 类型 | 规则说明 |
|---|---|---|
| Rule 8--0--01 | Required | 函数体/构造函数体/析构函数体须在类定义中或类外定义 |
| Rule 8--3--01 | Required | 重写虚函数的参数默认值须与被重写函数一致 |
| Rule 8--4--01 | Required | 禁止使用省略号(...)传参 |
| Rule 8--4--02 | Required | 函数参数应具名(文档化) |
| Rule 8--4--03 | Required | 非 void 返回类型函数的所有路径须包含 return |
| Rule 8--4--04 | Required | return 须出现在函数体中或无条件执行 |
| Rule 8--5--01 | Required | 所有变量在读取前须初始化 |
| Rule 8--5--02 | Required | 数组和结构体的非零初始化须使用大括号 |
| Rule 8--5--03 | Required | 枚举列表中除非全部初始化否则应显式初始化 |
第 9 章: 异常与特殊函数(8 条规则)
| 规则编号 | 类型 | 规则说明 |
|---|---|---|
| Rule 9--3--01 | Required | const 成员函数不可返回非 const 指针/引用 |
| Rule 9--3--02 | Required | 成员函数不可返回非 const 句柄 |
| Rule 9--3--03 | Required | 可声明为 static 或 const 的成员函数须声明 |
| Rule 9--5--01 | Required | 禁止使用 union |
| Rule 9--6--01 | Document | 位字段在目标平台上的绝对定位须文档化 |
| Rule 9--6--02 | Required | 位字段须为 signed int 或 unsigned int |
| Rule 9--6--03 | Required | 位字段不可使用枚举类型 |
| Rule 9--6--04 | Required | 非 bool 类型的位字段不可为 1 位 |
第 10 章: 环境(6 条规则)
| 规则编号 | 类型 | 规则说明 |
|---|---|---|
| Rule 10--1--01 | Advisory | 类不应从虚基类派生 |
| Rule 10--1--02 | Required | 基类仅在钻石继承中声明为 virtual |
| Rule 10--1--03 | Required | 可访问基类不可在同一继承层次中同时为 virtual 和非 virtual |
| Rule 10--2--01 | Advisory | 多重继承层次中的所有可访问实体名称应无歧义 |
| Rule 10--3--01 | Required | 虚函数在继承路径上须有唯一最终重写 |
| Rule 10--3--03 | Required | 虚函数仅可由 virtual 函数重写 |
第 11 章: 位字段(1 条规则)
| 规则编号 | 类型 | 规则说明 |
|---|---|---|
| Rule 11--0--01 | Required | 非 POD 类的成员数据不可为 public |
第 12 章: 派生类(5 条规则)
| 规则编号 | 类型 | 规则说明 |
|---|---|---|
| Rule 12--1--01 | Required | 构造函数或析构函数中不可使用对象的动态类型 |
| Rule 12--1--02 | Advisory | 所有构造函数应显式调用所有直接基类和虚基类的构造函数 |
| Rule 12--1--03 | Required | 可用单参数调用的构造函数须声明为 explicit |
| Rule 12--8--01 | Required | 复制构造函数仅初始化基类和成员 |
| Rule 12--8--02 | Required | 复制赋值运算符须声明为 protected 或 private 或 = delete |
第 14 章: 重载(10 条规则)
| 规则编号 | 类型 | 规则说明 |
|---|---|---|
| Rule 14--5--01 | Required | 非成员 friend 函数仅在包含类定义的命名空间中声明 |
| Rule 14--5--02 | Required | 存在单参数模板构造函数时须声明复制构造函数 |
| Rule 14--5--03 | Required | 存在模板赋值运算符时须声明复制赋值运算符 |
| Rule 14--6--01 | Required | 依赖基类的类模板中须使用 this-> 或 Base:: |
| Rule 14--6--02 | Required | 重载解析选中的函数须在该翻译单元中先前声明 |
| Rule 14--7--01 | Required | 所有类模板、函数模板、模板成员函数和模板静态成员须实例化 |
| Rule 14--7--02 | Required | 模板特化中的 explicit 声明不可导致程序 ill-formed |
| Rule 14--7--03 | Required | 模板的所有部分和显式特化须在首次使用前声明 |
| Rule 14--8--01 | Required | 重载函数模板禁止显式特化 |
| Rule 14--8--02 | Advisory | 函数调用的可行函数集合应仅包含函数或仅包含函数模板 |
第 15 章: 库 --- 通用(17 条规则)
| 规则编号 | 类型 | 规则说明 |
|---|---|---|
| Rule 15--0--01 | Document | 异常仅用于错误处理 |
| Rule 15--0--02 | Advisory | 异常对象不应为指针类型 |
| Rule 15--0--03 | Required | 不可将控制转入 try / catch 或 function-try-block |
| Rule 15--1--01 | Required | 异常对象复制构造函数不可抛出异常 |
| Rule 15--1--02 | Required | 禁止抛出空 throw;(即 throw 不是一个表达式) |
| Rule 15--1--03 | Required | 空的 throw 处理程序(重新抛出当前异常)须注意 |
| Rule 15--3--01 | Required | 异常仅可在程序启动后和终止前抛出 |
| Rule 15--3--02 | Advisory | 至少应有一个处理器捕获所有异常 |
| Rule 15--3--03 | Required | 类构造函数/析构函数的 handler 不可引用非静态成员 |
| Rule 15--3--04 | Required | 显式抛出的异常在所有调用路径中须有兼容类型的 handler |
| Rule 15--3--05 | Required | 类类型异常必须按引用捕获 |
| Rule 15--3--06 | Required | 多个 handler 的顺序须从基类到派生类排列 |
| Rule 15--3--07 | Required | 如果有 catch(...) 则须放在最后 |
| Rule 15--4--01 | Required | 函数异常规约在所有声明中须一致 |
| Rule 15--5--01 | Required | 析构函数不可因异常退出 |
| Rule 15--5--02 | Required | throw() 异常规约函数须仅抛出指示类型的异常 |
| Rule 15--5--03 | Required | unexpected() 函数不可隐式调用 |
第 16 章: 标准库(19 条规则)
| 规则编号 | 类型 | 规则说明 |
|---|---|---|
| Rule 16--0--01 | Required | #include 后只允许预处理指令或注释 |
| Rule 16--0--02 | Required | 宏不可被 #undef 或在全局命名空间中再次定义 |
| Rule 16--0--03 | Required | 应使用 #ifndef / #define / #endif include guard |
| Rule 16--0--04 | Required | 函数宏应由函数替代 |
| Rule 16--0--05 | Required | 函数宏的实参不可含类似预处理指令的内容 |
| Rule 16--0--06 | Required | 宏参数替换后须加括号 |
| Rule 16--0--07 | Required | # 或 ## 操作符仅用于 #if / #elif 操作数以外的位置 |
| Rule 16--0--08 | Required | #if / #elif 后须紧跟预处理标识符 |
| Rule 16--1--01 | Required | defined 操作符仅用于 #if / #elif |
| Rule 16--1--02 | Required | 所有 #else / #elif / #endif 须带注释指明所属的 #if / #ifdef |
| Rule 16--2--01 | Required | 优先使用 const / inline / template 替代宏 |
| Rule 16--2--02 | Required | C++ 宏仅用于 include guard 和条件编译 |
| Rule 16--2--03 | Required | 所有头文件须提供唯一 include guard |
| Rule 16--2--04 | Required | #line 中禁止使用 / 或 " 字符 |
| Rule 16--2--05 | Advisory | #line 中不应出现 \ 字符 |
| Rule 16--2--06 | Required | #include 后须跟 <filename> 或 "filename" |
| Rule 16--3--01 | Required | #if / #elif 中至多一个 defined |
| Rule 16--3--02 | Advisory | #if / #elif 中 defined 不应与逻辑运算符组合 |
| Rule 16--6--01 | Document | 所有 #pragma 的使用须文档化 |
第 17 章: 输入输出(5 条规则)
| 规则编号 | 类型 | 规则说明 |
|---|---|---|
| Rule 17--0--01 | Required | 标准库保留名称不可被复用 |
| Rule 17--0--02 | Required | 标准库宏和对象的名称不可被复用 |
| Rule 17--0--03 | Required | 标准库函数的名称不可被复用 |
| Rule 17--0--04 | Document | 所有库代码须符合 MISRA C++ |
| Rule 17--0--05 | Required | setjmp / longjmp 禁止使用 |
第 18 章: 动态内存(8 条规则 --- 功能安全最关键的章节)
| 规则编号 | 类型 | 规则说明 |
|---|---|---|
| Rule 18--0--01 | Required | C 标准库禁止使用 (<cstdlib>、<cstring>、<cstdio> 等) |
| Rule 18--0--02 | Required | <cstring> 库函数禁止使用 |
| Rule 18--0--03 | Required | <cstdlib> 的 exit() / abort() 禁止使用 |
| Rule 18--0--04 | Required | <ctime> 的时间处理函数禁止使用 |
| Rule 18--0--05 | Required | <cstring> 的无界函数(strcpy、strcmp、strcat 等)禁止使用 |
| Rule 18--2--01 | Required | offsetof 宏禁止使用 |
| Rule 18--4--01 | Required | 动态堆内存分配禁止使用 (new / delete / malloc / free 全部禁止) |
| Rule 18--7--01 | Required | <csignal> 信号处理设施禁止使用 |
第 19 章: 预处理(1 条规则)
| 规则编号 | 类型 | 规则说明 |
|---|---|---|
| Rule 19--3--01 | Required | errno 的错误指示须正确测试和处理 |
第 27 章: 杂项(1 条规则)
| 规则编号 | 类型 | 规则说明 |
|---|---|---|
| Rule 27--0--01 | Required | 流 IO 库(<cstdio> 的 perror / rename / remove 等)禁止使用 |
五、对车载功能安全项目的建议
5.1 ASIL 等级与规则子集对应
| ASIL 等级 | 必须遵守的规则 | 建议补充 |
|---|---|---|
| QM | Required 规则 (198 条) | Advisory 规则酌情 |
| ASIL A | Required + Document | Advisory 规则推荐 |
| ASIL B | Required + Document + 大部分 Advisory | 全部规则 |
| ASIL C | 全部 226 条规则 | 结合 AUTOSAR C++14 |
| ASIL D | 全部规则 + 静态分析工具鉴定 | 推荐升级到 AUTOSAR C++14 |
5.2 工具链建议
因 MISRA C++:2008 基于 C++03,实践中需注意:
编译器(需 TÜV 安全认证):
- GHS (Green Hills) --- 推荐
- Tasking --- 推荐
- Hightec GCC --- 推荐
- IAR Embedded Workbench with Safety认证
静态分析工具:
- QAC (Perforce) --- 原生 MISRA C++:2008 全规则覆盖
- LDRA --- 完整规则覆盖
- SonarQube --- SonarCXX 插件支持
- Polyspace Bug Finder (MathWorks)
单元测试工具:VectorCAST、Tessy
5.3 规则实施优先级建议
高级别组(必须修复):
Rule 18--4--01 → **动态内存分配检查**
Rule 18--0--01 → **C 标准库禁止**
Rule 0--1--01 → 不可达代码
Rule 0--1--09 → 死代码
Rule 5--2--04 → C-style cast 禁止
Rule 5--2--06 → 函数指针转换禁止
Rule 5--2--07 → 无关指针转换禁止
Rule 5--2--08 → 整数转指针禁止
Rule 7--5--01 → 悬空引用
Rule 6--6--05 → 函数单出口
中级别组(建议修复):
Rule 5--0--03 ~ 5--0--09 → 隐式类型转换
Rule 5--0--15 ~ 5--0--18 → 指针安全
Rule 6--4--03 ~ 6--4--08 → switch 结构规范
Rule 15--3--05 → 异常按引用捕获
Rule 7--5--04 → 递归禁止
Rule 18--4--01 → new / delete 禁止
低级别组(文档与治理):
Rule 0--3~0--4 系列 → 运行时错误处理文档化
Rule 16--6--01 → #pragma 文档化
Rule 17--0--04 → 所有库代码须符合 MISRA
5.4 重要注意事项
- MISRA C++:2008 基于 C++03 --- 现代 C++(C++11/14/17/20)功能如
auto、lambda、移动语义、std::shared_ptr、范围for循环等均不在规则覆盖范围内 - 对于新项目,强烈建议升级到 AUTOSAR C++14 Guidelines(免费,397 条规则,覆盖现代 C++)
- MISRA C++:2008 与 AUTOSAR C++14 不直接兼容 --- 迁移时需要重新进行规则偏差分析
- 建议配合 ISO 26262-6(软件级产品开发)中 Table 1~Table 13 的实施方法使用
- 使用静态分析工具时,建议开启所有 Required 级别规则,逐步推动 Advisory 级别规则
本报告基于 MISRA C++:2008 原始 PDF 文档提取生成,提取规则 226/228 条(2 条因编码未完全解析)。建议对照官方文档进行复核。