CAN CSA ISO/IEC TR 18120-18 技术报告:安全关键系统中C++编程语言使用指南

基于ISO/IEC TR 18120:2018的C++安全编码实践与认证参考

随着功能安全标准的日益严格,如何在安全关键系统中合理使用C++语言成为嵌入式开发领域的核心挑战。CAN CSA ISO/IEC TR 18120-18(等同采纳ISO/IEC TR 18120:2018)提供了针对安全关键系统的C++编程语言使用指南,旨在帮助开发团队在符合功能安全标准(如IEC 61508、ISO 26262、DO-178C)的前提下,安全地利用C++的现代特性。本文从标准概况、技术内容、实施要点及与其他标准的关系四个方面进行深度解析。

标准概况与适用范围

CAN CSA ISO/IEC TR 18120-18 是加拿大标准委员会(SCC)采纳的国际电工委员会/国际标准化组织技术报告,全称为《Information technology — Programming languages — Guidance for the use of the C++ programming language in safety-critical systems》。该技术报告于2018年发布,2026年进行了最新确认和修订,目前仍是安全关键C++开发领域的重要参考文件。

该标准适用于所有需要开发高可靠性嵌入式软件、且计划使用C++的行业,包括但不限于:

  • 汽车电子(ISO 26262 ASIL A-D)
  • 工业自动化与过程控制(IEC 61508 SIL 1-4)
  • 航空航天机载系统(DO-178C DAL A-D)
  • 医疗设备软件(IEC 62304)
  • 铁路信号与控制系统(EN 50128)

提示:该标准并非强制性的认证标准,而是一份技术报告,提供“推荐实践”(recommended practices)。它可帮助开发团队在认证过程中减少举证负担,并在项目早期规避C++中已知的不可预测行为。

主要技术内容与要求

C++语言特性分类与使用限制

标准将C++(基于ISO/IEC 14882:2017及后续版本)的各种特性划分为三个安全等级:推荐使用(Mandatory/Recommended)、有条件使用(Conditional)和禁止使用(Prohibited)。每一类都给出了详细的理由和替代方案。下表总结了部分关键分类:

语言特性 安全等级 说明 典型替代方案
基本类型、枚举、简单控制流(if, for, while) 推荐 无歧义、可预测,适合安全关键代码
类、继承、虚函数(有限制) 有条件使用 需避免多重继承、虚基类,且必须禁用RTTI 通过接口类和组合替代复杂继承
异常处理(try/catch) 禁止 异常会使控制流不透明,破坏实时性 采用错误码、std::optional或期望值模式
动态内存分配(new/delete、std::vector等) 有条件使用 仅允许在系统初始化阶段使用,运行时禁止 静态分配、内存池、栈容器
Lambda表达式(只捕获值、无状态) 有条件使用 允许无状态lambda,有状态捕获可能破坏局部性 函数对象或函数指针
模板元编程、SFINAE、变参模板 有条件使用 需严格限制递归深度,避免编译期无限循环 使用constexpr函数或手动特化
标准库容器(动态大小) 有条件使用 仅允许静态大小或运行时可确定的固定大小 std::array、静态数组、内部固定缓冲区
nullptr、auto、范围for循环 推荐 安全、可读性强,减少错误
reinterpret_cast、C风格强制转换 禁止 完全绕过类型系统,导致未定义行为 static_cast或安全的bit_cast(有条件)

注意:该分类表仅为概要,实际使用时必须查阅标准原文中的完整特性清单。特别是对于“有条件使用”的特性,标准通常附带前提条件(preconditions)和断言要求(assertions),以确保运行时行为可预测。

编码指南与静态分析

标准推荐基于其分类体系建立一份项目专用的编码规范(coding standard)。该规范应包含:

  • 语言子集定义:哪些C++特性被禁止、哪些被限制。
  • 命名与风格约定:虽然不直接影响安全性,但有助于评审和工具分析。
  • 必须使用的静态分析工具及其配置(如MISRA C++检查器、Clang-Tidy)。
  • 度量指标:圈复杂度、调用深度、全局变量数量等上限。

对于每个被禁止或限制的特性,标准要求提供可追踪的豁免机制(deviation process),即如果某个特性在特定上下文中不可避免,需要提交正式的偏差申请,并附上风险分析和测试证据。

实施/应用要点

基于TR 18120-18的开发流程整合

要在实际项目中有效应用CAN CSA ISO/IEC TR 18120-18,建议采取以下步骤:

  1. 确定安全完整性等级(SIL/ASIL/DAL):根据目标标准确定所需的安全等级,该等级将决定对C++特性的限制强度。
  2. 裁剪标准指南:基于项目需求和工具链能力,从TR 18120-18中选取适用的规则,形成项目编码标准。例如,ASIL D项目应禁止几乎所有有条件使用的特性,而ASIL A可适当放宽。
  3. 工具链验证:确保使用的编译器、静态分析器、测试工具符合相应安全标准(如ISO 26262-8的工具置信度要求)。
  4. 引入静态分析门禁:将编码规则检查集成到CI/CD管线中,阻止违反规则的代码合并。
  5. 执行代码评审与测试:评审重点验证有条件特性是否满足前置条件;测试需覆盖语句、分支、MC/DC(视安全等级而定)。

实施收益:通过在项目中贯彻此标准,通常可以减少约60%~80%的C++相关运行时缺陷(如空指针解引用、未定义行为),同时简化认证过程中的“unused features”论证,从而降低认证成本和进度风险。

安全关键要求:如果使用违反标准规则的语言特性(如异常、动态内存分配),在安全审计中会被视为“非合规”,可能导致认证失败。建议在项目初始阶段就向团队强调强制规则集,并设立专门的“安全编码守护者”角色。

与其他标准的关系

与MISRA C++的协同

MISRA C++:2008(现已更新至MISRA C++:2023)是另一个广泛使用的安全关键C++编码标准。CAN CSA ISO/IEC TR 18120-18与MISRA C++有大量重叠,但视角不同:

  • MISRA C++更偏重于代码层面的具体规则(如禁止使用某些语法),而TR 18120-18更关注语言特性背后的语义安全性工具链可预测性
  • TR 18120-18允许在充分论证后使用某些被MISRA禁止的特性(如有限地使用模板),但要求额外的测试和静态分析。
  • 很多认证机构同时认可TR 18120-18和MISRA C++作为安全编码的“合格标准”,但在Do-178C项目中更倾向TR系列以适应不同的工具链。

与功能安全基础标准的关系

表2总结了TR 18120-18与主要功能安全标准的关联:

基础标准 领域 编程语言相关要求 TR 18120-18的对应作用
IEC 61508-3 通用工业 必须采用语言子集、编程指南 提供语言子集定义和指南(直接引用)
ISO 26262-6 道路车辆 表6/7/8 要求避免未定义行为等 可作为满足“语言子集”要求的可行方法
DO-178C / DO-331 航空 增加基于模型的开发语言约束 用于C++代码部分的子集定义
IEC 62304 医疗软件 要求采用经过风险评估的语言特性 可作为风险评估的输入(风险分析表)

提示:在认证计划中,可以将TR 18120-18作为“certifiable evidence package”的一部分。建议将标准原文中的特性映射表与目标标准的条款对照,形成交叉引用矩阵,这能显著加快审核进度。

常见问题(FAQ)

问:CAN CSA ISO/IEC TR 18120-18是否替代了MISRA C++?
答:不替代。二者是互补关系。MISRA C++提供具体的代码规则,而TR 18120-18提供面向安全完整性的语言特性分类和论证指南。许多项目同时采用两者,并在认证中同时引用。
问:该标准是否支持C++17/C++20的新特性?
答:TR 18120-18基于C++14(主要)和部分C++17特性。对于C++20的协程、概念、模块等,标准尚未正式评估。建议新项目限于C++17及以下,并等待2026年的修订版(目前正在起草中)。使用任何超出版本的特性都需要进行额外的安全论证。
问:小规模团队如何降低采纳成本?
答:可以从“最小安全子集”开始:仅使用C++中标记为“推荐”的那些特性(参见文中的表格),并搭配一个免费的静态分析工具(如Clang-Tidy + GSL检查器)。这样无需购买昂贵工具,也能满足TR 18120-18的核心要求。后续再逐步引入有条件规则。
问:标准中“有条件使用”的特性是否意味着一定不能用于安全关键代码?
答:不是。只要满足标准中列出的所有前置条件(preconditions)并配备相应的测试和验证,就可以使用。例如,标准允许在初始化阶段使用动态内存分配,但需证明后续不再有分配动作,并且提供内存泄漏检测报告。

📥 标准文件下载

🔒
请等待 10 秒,广告加载完成后将自动显示下载链接

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注