News Hacker|极客洞察

243 3 小时前 youtube.com
🛡战机为何禁用九成C++特性:为确定性与任务保证
真相信禁 90% C ++就能防止坠机?

🎯 讨论背景

视频以 JSF/F‑35 的 C++ 编码规范为切入点,讨论为何航电软件在 C++ 中禁用了大量特性以换取确定性、可证明的时序与远程故障恢复能力。评论把话题扩展到行业标准(如 MISRA、AUTOSAR、DO‑178C)、Ada vs C++ 的历史与人才问题、以及工程实践细节(静态地址、MMU 重映射、双份 OS、禁用 exceptions 与动态分配)。技术讨论还包括 Simulink/autocode 的系统级权衡与 GLib 在纯 C 中用 cleanup attribute 实现类似 RAII 的做法,反映出语言选择、工具链与采购/治理因素的复杂交织。

📌 讨论焦点

确定性与任务保证(语言子集)

军用航电并非出于“讨厌 C++”而禁用大量特性,而是为了可预测性和 mission assurance。任何会隐藏分配、引入不可预见控制流或让 WCET(最坏情况执行时间)分析复杂化的特性都会被剔除:例如禁止 exceptions、运行期堆分配、STL、multiple inheritance、dynamic_cast 等,但保留 RAII(析构函数)以保证作用域内确定性清理。JSF/F‑35 的 C++ 规范明确写明“初始化后不得向 free store 分配/释放”,把语言缩减为一个可审计、静态可分析的子集。评论反复指出,在这种约束下,语言差异被弱化,任何“C 风格”语言都能满足大部分需求。

[来源1] [来源2] [来源3] [来源4]

内存故障、静态地址与远程调试

航电关注的是在现场故障(比如物理内存单元失效)下仍能继续任务,因此常用静态地址与确定性布局:如果某地址挂了,可以下发补丁把重要变量移动到别的位置。评论讨论了工程级补救手段:用 ECC/冗余编码(例如 Reed‑Solomon)处理整块失效、在启动时 blacklist 坏块、或用 MMU 在运行时把逻辑页重映射到良好物理页。远程故障排查要求地面能用“相同的静态映像”精确复现,超低带宽下无法做交互式调试,因此静态可复现性和确定性比动态策略更重要。还有建议采用双份 OS 映射或备份引导来提高恢复能力。

[来源1] [来源2] [来源3] [来源4] [来源5]

Ada 与 C++ 的历史权衡

历史上航电行业曾偏好 Ada,但政府/项目层面的强制策略后来被撤销,部分原因是难以招聘足够 Ada 开发者及配套生态不足。评论里有人认为若政府强制推 Ada,大学与培训会跟进;也有人指出成为“单一大客户”会抬高成本,撤销 Ada 强制是出于成本/供应考虑。另有观点认为今天 Ada(及其安全子集 SPARK)更易被接受,且在特定高安全场景下仍有优势。政治与采购因素(如瑞士采购争议)也被提及,说明语言选择不仅是技术决定。

[来源1] [来源2] [来源3] [来源4]

编码标准、MISRA 与实际效果的争论

MISRA 与类似标准在行业内被广泛采用,但评论指出其效果参差:部分规则有益(避免 UB 等显而易见的问题),但也有规则被研究证明有害或是纯粹风格约束。批评集中在标准被官僚化执行、用于掩盖流程缺陷,以及自动化工具生成的“合规却难维护”代码。支持者回应说,对于 DO‑178C/高可靠场景,大量测试、流程与审核能把现场缺陷率压低;同时行业也在演进(如 AUTOSAR 与 MISRA 在 C++ 方面的整合与 MISRA C++ 2023)。

[来源1] [来源2] [来源3] [来源4] [来源5]

自动代码生成(Simulink/autocode)的利弊

Simulink/autocode 在航天与航空圈既有支持者也有反对者。支持者认为模型级验证能消除人工敲代码时的低级错误,并且在若干航天项目中已被实际使用;反对者指出 autocode 常导致代码臃肿、资源占用高、可读性差,还可能触发编译器的边界缺陷(例如超大 switch 的跳转问题)。评论强调权衡点在于:autocode 能降低某类人为错误但会把复杂度转移到硬件选型、系统级设计和认证/测试矩阵上;个别事件(如 Toyota 案例)不能简单作为因果证据。

[来源1] [来源2] [来源3] [来源4]

GLib 在 C 中实现自动清理(C 的 RAII 替代)

GLib 利用 GCC/Clang 的 cleanup attribute 实现了类似 C++ 析构的语义:g_autofree、g_autoptr、g_auto 与 G_DEFINE_AUTOPTR_CLEANUP_FUNC 等宏在变量出作用域时自动调用合适清理函数。配合 GObject 的引用计数与 g_malloc/g_try_malloc,GLib 能把自动清理、自动释放错误对象等惯用模式带到纯 C 中,从而减少 malloc/free 漏洞与繁琐的清理逻辑。评论认为这是“把 C 做好”的实例,证明不一定要换语言也能获得类似 RAII 的工程效益。

[来源1] [来源2]

异常 vs 错误码及禁用异常的实践

在嵌入式和航电代码中,exceptions 常被禁用:理由包括异常会改变控制流、影响时序分析,且历史上某些实现的 throw 路径存在全局锁导致性能不可测。许多大公司(如 Google)与游戏引擎团队选择用错误码或显式检查替代 exceptions,尽量在关键路径避免隐藏成本。讨论也提到针对异常开销的研究与 ACCU/CppCon 演讲,表明在某些实现与配置下可以显著降低异常带来的二次开销,但工程上仍常以“可预测胜过灵活”为优先。

[来源1] [来源2] [来源3] [来源4] [来源5]

跨行业共识:不同领域采用类似受限子集

航电、广播 playout、HFT(高频交易)、游戏等多个领域在关键路径上都采用相似约束:静态内存分配、避免运行时分配、尽量不使用递归/异常和复杂库,以便证明实时性与稳定性。具体案例包括广播系统需要连续多年按时输出帧、HFT 对纳秒级延迟敏感、游戏在热路径避免隐式锁与分配。虽有评论指出现代 ML/AI 推理多为固定模型和固定输入形状而易于预分配,但也有人强调传感器/系统级瓶颈与任务规模会影响是否能坚持这种静态策略。

[来源1] [来源2] [来源3] [来源4]

F‑35 项目争议与现实评估

关于 F‑35 的评价在评论中两极分化:一些人把其视为预算超支和管理失败的典型,列举了早期缺陷(氧气问题、电气短路、过热等);但也有评论指出其生产数量庞大(上千架)、国际买家多,且在能力上处于同级前列。评论讨论了政治采购、盟友关系与项目管理教训,结论是技术能力与项目执行/采购策略需要区分,不能单凭耸动性报道下定论。有人进一步提出未来战争形态(无人机/导弹)会改变对传统战斗机长期价值的评估。

[来源1] [来源2] [来源3] [来源4] [来源5]

📚 术语解释

RAII: C++ 的资源管理惯用法(Resource Acquisition Is Initialization),对象构造时获取资源、析构时释放,以保证按作用域自动清理资源和避免泄露。

MISRA: MISRA(Motor Industry Software Reliability Association)为汽车与嵌入式领域制定的 C/C++ 编码指南,限制危险语言特性以便静态分析和可证明性,但有时被批评为僵化或被机械执行。

DO-178C: DO‑178C 是民用航空软件的认证与验证标准,定义软件开发过程、测试与文档要求,用于证明软件满足不同的安全等级(DAL)。

WCET: WCET(Worst‑Case Execution Time,最坏情况执行时间),实时/航电系统用来证明任务在最恶劣情形下仍能满足时序约束的重要度量。

cleanup attribute (GCC/Clang): GCC/Clang 的扩展属性,允许为局部变量指定在离开作用域时自动调用的清理函数,GLib 的 g_autofree/g_autoptr 等宏基于此实现自动释放语义。

Simulink/autocode: Simulink(MathWorks 的模型建模与仿真工具)提供 autocode(自动生成 C/C++ 代码)功能,常用于控制系统原型与认证,但会带来资源占用、可读性和验证矩阵方面的权衡。

AUTOSAR: AUTOSAR(Automotive Open System Architecture)是汽车行业的软件架构与规范组织,其 C++ 指南与 MISRA 等标准在汽车/嵌入式高可靠项目中被联合参考。