为什么不建议在空间/辐射环境中使用C ++模板?

Gui*_*e D 64 c++ embedded templates fault-tolerance

通过阅读此问题,例如,我理解了为什么在空间或核电站等辐射较高的环境中不建议动态分配或例外的原因。关于模板,我不知道为什么。你能给我解释一下吗?

考虑到这个答案,它说使用起来很安全。

注意:我不是在谈论复杂的标准库内容,而是针对性的自定义模板。

Bas*_*tch 107

请注意,与太空兼容(防辐射,符合航空航天标准)的计算设备非常昂贵(包括在太空中发射,因为它们的重量超过公斤),而且一次太空飞行任务可能耗资一亿欧元或美元。由于软件或计算机问题而丢失任务通常要付出高昂的代价,因此这是无法接受的,并且证明了昂贵的开发方法和过程是合理的,而您甚至都不曾梦想使用这些方法和过程来开发手机applet,因此建议使用概率推理和工程方法,因为宇宙射线仍然是某种“异常”事件。从高级的角度来看,宇宙射线及其产生的位翻转可以视为某种抽象形式的信号或输入的噪声。您可以将“随机位翻转”问题视为信噪比问题,然后随机算法可能会提供有用的概念框架(尤其是在元级别上,即在分析安全关键源代码或编译时)。二进制,也可以在关键的系统运行时,在某些复杂的内核或线程调度程序中,以信息论的观点。

为什么不建议在空间/辐射环境中使用C ++模板?

该建议是一个概括,对C ++的MISRA C编码规则和嵌入式C ++的规则,以及DO178C建议,它是不相关的辐射,但到嵌入式系统。由于辐射和振动的限制,任何太空火箭计算机的嵌入式硬件都必须非常小(例如,出于经济和能源消耗的原因,在计算机功能上,它是类似Raspberry Pi的系统,而不是大型x86服务器系统。 )。空间硬化芯片的成本是民用同类芯片的1000倍。在太空嵌入式计算机上计算WCET仍然是一项技术挑战(例如,由于CPU缓存)相关问题)。因此,在安全性要求很高的嵌入式软件密集型系统中,堆分配不受欢迎(您将如何处理其中的内存不足情况?或者如何证明您有足够的RAM用于所有实际运行时情况?)

请记住,在安全性至关重要的软件世界中,您不仅会以某种方式“保证”或“承诺”,而且肯定会(通常使用一些聪明的概率推理)评估自己软件的质量,而且还会评估用于进行构建(特别是:您的编译器和链接器;未经FAADGAC的书面许可,波音公司或空中客车公司将不会更改其用于编译其飞行控制软件的GCC交叉编译器的版本)。您的大多数软件工具都需要以某种方式批准或认证。

请注意,实际上,大多数C ++(但不是全部)模板内部都使用堆。标准C ++ 容器当然可以。编写从未使用堆的模板是一项艰巨的任务。如果有能力,则可以安全地使用模板(假设您确实信任C ++编译器及其模板扩展机制,这是最新的C ++编译器(例如GCCClang)的C ++前端最棘手的部分)。

我想出于类似(工具集可靠性)的原因,使用许多源代码生成工具(进行某种元编程,例如发出C ++或C代码)并不受欢迎。注意,例如,如果你使用bison(或的rpcgen在一些安全关键软件)(由编译makegcc),您需要评估(也许详尽测试)不仅gccmake,而且还bison。这是工程原因,而不是科学原因。请注意,某些嵌入式系统可能会使用随机算法,特别是为了巧妙地处理噪声。输入信号(可能是由于稀有的宇宙射线而导致的甚至随机位翻转)。证明,测试或分析(或只是评估)这种基于随机的算法是一个非常困难的话题。

还查看Frama-ClangCompCert,并注意以下几点:

  • C ++ 11(或之后的版本)是一种极其复杂的编程语言。它没有完整的形式语义。在全球范围内,只有几十人具备C ++的专业知识(可能大多数人都在其标准委员会中)。我能够使用C ++进行编码,但无法解释所有移动语义或C ++ 内存模型的微妙情况。而且,C ++实际上需要进行许多优化才能有效使用。

  • 制作无错误的C ++编译器非常困难,特别是因为C ++实际上需要棘手的优化,并且由于C ++规范的复杂性。但是当前的(实际上是最新的GCC或Clang)在实践中相当不错,并且它们几乎没有(但仍然有一些)残留的编译器错误。目前还没有适用于C ++的CompCert ++,制作一部需要几百万欧元或美元(但是,如果您可以收取这么多的钱,请通过电子邮件与联系,例如basile.starynkevitch@cea.fr,发送至我的工作电子邮件)。太空软件行业非常保守。

  • 很难创建一个好的C或C ++堆内存分配器。编码是一个权衡的问题。开个玩笑,考虑使此C堆分配器适应C ++。

  • 事实证明,与模板相关的C ++代码的安全属性(特别是缺少竞争条件未定义的行为,例如运行时缓冲区溢出)在2019年第二季度仍比 C ++代码的静态程序分析技术要先进一些。我的Bismon技术报告草稿(这是H2020的可交付成果草稿,因此请跳过欧洲官僚的页面)有几页对此进行了更详细的说明。注意赖斯定理

  • 整个系统的C ++嵌入式软件测试可能需要发射火箭(la Ariane 5测试飞行501,或至少在实验室进行的复杂而繁重的实验)。这非常昂贵的。即使在地球上进行测试,火星探测器也需要大量资金。

想一想:您正在编写一些对安全性至关重要的嵌入式软件(例如,用于火车制动,自动驾驶汽车,自动驾驶无人机,大型石油平台或炼油厂,导弹等)。您天真地使用了一些C ++标准容器,例如some std::map<std::string,long>。内存不足情况该怎么办?您如何“证明”(或至少“说服”)在资助1亿欧元太空火箭的组织中的工作人员,您的嵌入式软件(包括用于构建它的编译器)足够好?十年前的规则是禁止任何类型的动态堆分配。

我不是在谈论复杂的标准库内容,而是专门针对性的自定义模板。

即使是这些也很难证明,或更一般地说,很难评估它们的质量(您可能希望在其中使用自己的分配器)。在空间上,代码空间是一个强大的约束。因此,您可以使用g++ -Os -Wall或进行编译clang++ -Os -Wall。但是,您如何证明(或只是测试)通过的所有细微优化-Os(这些特定于您的GCC或Clang版本)?您的太空资助组织会问您,由于嵌入式C ++太空软件中的任何运行时错误都可能使任务崩溃(请再次阅读有关Ariane 5首次飞行失败的信息-用Ada的某些方言编码,当时该词具有“更好的”含义,比“今天的C ++ 17”更“安全”的类型系统),但不要对欧洲人笑太多。波音737 MAX以其MACS类似的一团糟)。


我个人的建议(但请不要太在意。在2019年,它比其他任何事情都更容易理解)将是考虑使用Rust编写您的太空嵌入式软件。因为它比C ++更安全。当然,您将需要在5到7年内花费5到1000万欧元(或MUS $),以获得适用于太空计算机的优质Rust编译器(同样,如果您有能力花费,请与我专业联系)免费软件Compcert / Rust之类的编译器)。但这只是软件工程和软件项目管理的问题(有关更多信息,请阅读《神话般的月刊》和《胡说八道》,也请注意迪尔伯特原理。:它适用于太空软件行业或嵌入式编译器行业,以及其他任何方面。

我的强烈个人观点是,欧盟委员会应资助(例如通过Horizo​​n Europe)类似项目的免费软件 CompCert ++(或什至更好的Compcert / Rust),并且该项目需要5年以上且5次以上级博士研究人员)。但是,在60岁那年,我很遗憾地知道这将不会发生(因为EC意识形态-主要是出于明显的原因而受到德国政策的启发-仍然是“历史终结”的假象,因此H2020和Horizo​​n Europe在实践中,主要是通过欧洲避税天堂为欧洲公司实施税收优化的方法,并且在与CompCert项目的几个成员进行了几次私下讨论之后。我很遗憾地期望DARPANASA更有可能资助某些未来的CompCert / Rust项目(比EC资助)。


注意 欧洲航空电子业(主要是空中客车公司)正在使用比北美航空(波音公司)更为正式的方法。因此,避免了某些(并非全部)单元测试(由于用源代码的形式化证明代替,可能是使用了诸如Frama-CAstrée之类的工具-均未通过C ++认证,仅针对C禁止C动态内存分配子集和C的其他功能)。这是由DO-178C允许(而不是前身DO-178B)并由法国监管机构DGAC批准的(我猜也是由其他欧洲监管机构批准)。

另请注意,许多SIGPLAN会议与OP的问题间接相关。

  • 我发现您的C ++模板示例为`std :: map &lt;std :: string,long&gt;`令人怀疑,然后您出于动态分配的原因而反对它,而不是因为它是模板。我猜您想对动态分配进行详细介绍,因为OP在介绍了代码膨胀的模板之后也提到了动态分配,这是使验证变得更加困难的一般复杂性的一部分。如果您考虑自己在做什么,可以安全地使用模板,但是要确保代码膨胀很容易。 (7认同)
  • 这与模板有何关系? (4认同)
  • “由于嵌入式C ++空间软件中的任何运行时错误都可能使任务崩溃(再次阅读有关Ariane 5的首次飞行失败的消息,”尽管如此,这也不是支持嵌入式空间C的理由。C++具有更强大的类型检查功能,在这种情况下有帮助。 (3认同)
  • 回复:对安全至关重要的系统生锈:https://iron-systems.com/blog/sealed-rust-the-pitch/ (3认同)
  • 我发现这些有关C ++语言复杂性的论点令人信服。如果选择的语言是C,则它们将是有效的。但是我在某处读到Ada是他们的首选语言,它也是一种复杂的语言,我认为可以与C ++相提并论(尽管我承认我从未真正使用过它,但我只是在80年代开发时才读过规范。 )。 (2认同)
  • @Barmar如果说服C ++标准委员会,它应该说服您。在C语言中,未定义行为的区域数量非常有限,并且在标准中明确未定义区域。(鼻恶魔等。)在C ++中,标准委员会实际上“停止了计数”,因为有太多的跟踪对象。 (2认同)
  • @ReuvenAbliyev:IMO,这些“流离失所”的评论是由于OP是一个相当无效的主题。模板的使用和对辐射的鲁棒性之间有什么联系吗?或者介于驼色肠衣和耐火之间?:-) (2认同)

use*_*709 8

反对在安全代码中使用模板的观点是,认为模板会增加代码的复杂性而没有真正的好处。如果您使用的工具不好并且有经典的安全概念,则此论点是有效的。请看以下示例:

template<class T>  fun(T t){
   do_some_thing(t);
}
Run Code Online (Sandbox Code Playgroud)

用经典的方法来指定安全系统,您必须提供代码的每个功能和结构的完整描述。这意味着没有规范就不允许有任何代码。这意味着您必须以常规形式完整描述模板的功能。由于明显的原因,这是不可能的。顺便说一句,同样的原因也禁止类似函数的宏。如果以描述此模板的所有实际实例的方式改变了想法,则可以克服此限制,但是您需要适当的工具来证明您确实描述了所有模板。

第二个问题是:

fun(b);
Run Code Online (Sandbox Code Playgroud)

该行不是独立的行。您需要查找b的类型以知道实际调用了哪个函数。理解模板的正确工具在这里有帮助。但是在这种情况下,确实使手动检查代码变得更加困难。

  • “反对在安全代码中使用模板的论点是,认为模板会增加代码的复杂性而没有真正的好处。” 不,这是反对在整体嵌入式系统中使用模板的争论。反对在安全代码中使用模板的观点是,对于100%确定性代码中的模板,根本没有使用。在这样的系统中,任何地方都没有通用编程。您不能使用std :: vector之类的东西,因为您不太可能找到符合安全标准的std lib。否则,将花费大量现金。 (4认同)
  • @Lundin嵌入式世界中的泛型编程是一回事。甚至是深入的嵌入式东西。对于相同的原因,为什么它已成为其他方面的事情:经过良好测试的算法是一件好事。 (2认同)
  • @Lundin:模板与确定性或非确定性代码无关。最后,它们只是一种无需动态调度(虚拟函数或函数指针)和无需复制粘贴代码即可重用代码的方法,同时比宏更安全。例如,重用相同的排序算法对整数数组和短裤数组进行排序。std::vector 不适用于安全关键实时代码这一事实与它是模板无关。 (2认同)
  • 谁做?对于通用算法库的作者来说可能就是这种情况,但是当我们谈论安全关键的实时代码时,我们无论如何都离开了“通用”领域,而且OP也明确谈论了专门制作的自定义模板。 (2认同)
  • “这意味着您必须以通用形式给出模板功能的完整描述”——显式实例化将使用的每个模板类型,然后提供每个模板的功能的完整描述还不够吗?这样创建的类型? (2认同)