编码标准与合规要求
C++ 传统上占据的领域,其错误代价不是用损失的金钱来衡量,而是用人的生命来衡量:汽车电子、医疗设备、航空电子、工业自动化、轨道交通。在这类项目中,语言的自由反而成了问题,因此它会被约束——用一套编码规则、强制性的检查和文档化的开发流程。
这篇文章是这片领域的一张概览地图,而不是一份认证指南。它的目标是让你在招聘启事上看到”MISRA 经验”或”ISO 26262 项目”时明白它在说什么,并知道去哪里查找细节。
标准和要求非常多,下面只收录了其中最显眼的。并不存在一个统一的”必备集合”:每个项目都会根据行业、国家、客户和关键性等级使用自己的子集。只有当某个具体标准真的出现在你的项目上时,去深入研究它才有意义,而不是提前储备。
要求和期限会变化。在做决定之前,请对照标准的当前版本、并与你公司的法务核实——这篇文章用于建立方向感,而不是用于得出法律结论。
编码标准
它们把语言限制到一个更不容易搬起石头砸自己脚的子集:禁止在初始化之后动态分配内存、禁止异常、禁止隐式类型转换等等。是否遵守由静态分析器来检查——这样的规则集不靠人工核对。
-
MISRA C++:2023 - misra.org.uk安全关键系统中最著名的 C++ 规则集。它取代了 MISRA C++:2008,覆盖 C++17。一个重要的变化是:它吸收了 AUTOSAR C++14 的指南,因此不再像以前那样有两套相互竞争的规则集,现在只有一套在向前发展。如果你遇到一个基于 AUTOSAR C++14 的项目,那就是同一套思路的上一代(autosar.org)。
-
SEI CERT C++ - wiki.sei.cmu.edu一套以安全为重点的规则集:如何避免会导致漏洞的写法。与 MISRA 不同,它免费且公开——即使你的项目不做认证,它也是了解这一类标准本身的好途径。
-
C++ Core Guidelines - isocpp.github.io来自 Bjarne Stroustrup 和 Herb Sutter 的建议。与 MISRA 不同,它们不是限制语言,而是恰恰相反——推动你走向现代风格。它们在形式上不是监管文件,但对任何 C++ 开发者都有用;其中一部分可以通过
clang-tidy和 Microsoft GSL 来检查。
功能安全
这些标准回答的问题是”要发生什么,系统在失效时才不会造成伤害”。它们规范的与其说是代码,不如说是流程:需求、可追溯性、测试、文档,以及所用工具的资格认定。
这个领域的基础标准是 IEC 61508,它引入了安全完整性等级 SIL 1-4。下面这些行业标准是它的具体化:
-
ISO 26262 - 汽车 - iso.org道路车辆的功能安全。它引入了从 A 到 D 的 ASIL 等级,其中 D 最严格(例如刹车或转向控制)。”ISO 26262 + MISRA C++”这个组合最常出现的地方就是这里。
-
IEC 62304 - 医疗软件 - iso.org医疗器械的软件生命周期。它根据失效是否可能导致健康损害以及损害的严重程度,定义了 A、B、C 三个安全等级。遵守这个标准,是证明符合欧洲医疗器械法规 MDR(Regulation (EU) 2017/745)以及美国 FDA 要求的主要途径。
-
DO-178C - 航空电子 - rtca.org机载软件的要求。DAL 关键性等级从 A 到 E;A 级尤其要求对逻辑表达式中的各个条件层面进行测试覆盖(MC/DC)。它被认为是业内遵守起来最严苛、最昂贵的标准之一。
网络安全与供应链
对 C++ 世界来说这是一个相对较新的话题:监管机构正在把漏洞的责任转移到软件供应商身上。
-
EU Cyber Resilience Act (CRA) - digital-strategy.ec.europa.eu一项欧盟法规,覆盖供应到欧洲市场、带有数字元素的产品——从工业控制器到消费电子。它要求进行安全的开发、在支持期内发布安全更新,并对正在被主动利用的漏洞进行通报。它于 2024 年 12 月生效,主要义务从 2027 年底起适用,通报义务则更早。重要的是,它影响的不只是”安全关键”行业,而是几乎任何作为在售产品一部分的软件。
-
SBOM(软件物料清单,Software Bill of Materials) - spdx.dev, cyclonedx.org一份机器可读的清单,列出进入交付软件中的所有组件和依赖——就像包装上的配料表那样的”产品成分”。有了它,当某个流行的库中发现漏洞时,就能迅速回答”我们有没有用到它”这个问题。两种主要格式是 SPDX 和 CycloneDX,二者都已标准化。对 C++ 来说这个话题很实在:依赖常常以源码形式引入或手工构建,没有 SBOM 的话,究竟什么进入了构建往往并不明显。
这在实践中意味着什么
如果你进入这样一个项目,改变的与其说是语言,不如说是代码周围的环境:
- 语言子集。 一部分熟悉的特性会被禁用——通常是初始化后的动态内存、异常、RTTI,有时还包括模板和整个标准库。
- 强制静态分析。 构建不仅会因编译器错误而失败,也会因违反规则而失败。对规则的偏离要以书面形式记录并获得批准,而不是在代码里简单地抑制掉。
- 可追溯性。 对每一行代码,都能追溯它来自哪条需求、由哪个测试覆盖。因此对任务和提交的书写方式有很高的要求。
- 工具资格认定。 编译器、分析器和测试框架也需要被论证——正因如此,版本很少更新,”直接上最新的 GCC”并不总是可行。
- 繁重的评审和文档。 配套文档的体量可能超过代码本身,而工期也可能明显长于普通开发。
谁真正需要这些
不是所有人。 如果你写游戏、桌面应用、后端或者交易系统,实际上你很可能不会碰到这些标准,也没必要专门去学。
只有当你走向汽车电子、医疗设备、航空、航天、轨道交通或工业自动化时,这个话题才变成必修。对其他人来说,知道这些标准存在、以及它们大致讲什么就够了——面试时这样就够用。
例外是 CRA 和 SBOM。它们涉及的产品范围比传统的功能安全要广得多,因此即便是产品在欧洲销售的”普通”开发者,也值得去了解一下它们。