通过阅读此问题,例如,我理解了为什么不建议在空间或核电站等辐射较高的环境中进行动态分配或例外处理。关于模板,我不知道为什么。你能给我解释一下吗?
考虑到这个答案,它说使用起来很安全。
注意:我不是在谈论复杂的标准库内容,而是在专门定制模板。
auto
)将使您大吃一惊。
Answers:
请注意,与空间兼容的(辐射硬化的,符合航空航天标准的)计算设备非常昂贵(包括在太空中发射,因为它们的重量超过了千克),而且一次太空飞行可能要花费1亿欧元或美元。由于软件或计算机问题而失去任务通常要付出高昂的代价,因此这是无法接受的,并且证明了开发手机小程序根本不希望使用的昂贵的开发方法和过程,并且建议使用概率推理和工程方法,因为宇宙射线仍然是某种“异常”事件。从高级的角度来看,宇宙射线及其产生的位翻转可以视为某种抽象形式的信号或输入的噪声。您可以将“随机位翻转”问题视为信噪比问题,然后随机算法可以提供有用的概念框架(尤其是在元级别,即在分析安全关键源代码或编译时)。二进制,也可以在关键的系统运行时,在某些复杂的内核或线程调度程序中,以信息论的观点。
为什么不建议在空间/辐射环境中使用C ++模板?
该建议是一个概括,对C ++的MISRA C编码规则和嵌入式C ++的规则,以及DO178C建议,它是不相关的辐射,但到嵌入式系统。由于辐射和振动的限制,任何太空火箭计算机的嵌入式硬件都必须非常小(例如,出于经济和能源消耗的原因,与大型x86服务器系统相比,在计算机功能上,它更像Raspberry Pi) )。空间硬化芯片的成本是民用同类芯片的1000倍。在太空嵌入式计算机上计算WCET仍然是一项技术挑战(例如,由于CPU缓存)相关问题)。因此,在安全性要求很高的嵌入式软件密集型系统中,堆分配不受欢迎(您将如何处理其中的内存不足情况?或者如何证明您有足够的RAM用于所有实际运行时情况?)
请记住,在安全性至关重要的软件世界中,您不仅会以某种方式“保证”或“承诺”,而且肯定会(通常使用一些聪明的概率推理)评估您自己的软件的质量,而且还会评估用于进行构建(尤其是:您的编译器和链接器;未经FAA或DGAC的书面许可,波音公司或空中客车公司将不会更改其用于编译其飞行控制软件的GCC交叉编译器的版本)。您的大多数软件工具都需要以某种方式批准或认证。
请注意,实际上,大多数C ++(但不是全部)模板内部都使用堆。标准C ++容器当然可以。编写从未使用堆的模板是一项艰巨的任务。如果有能力,您可以安全地使用模板(假设您确实信任C ++编译器及其模板扩展机制,这是最新的C ++编译器(例如GCC或Clang)的C ++前端最棘手的部分)。
我想出于类似(工具集可靠性)的原因,使用许多源代码生成工具(进行某种元编程,例如发出C ++或C代码)并不受欢迎。注意,例如,如果你使用bison
(或的rpcgen在一些安全关键软件)(由编译make
和gcc
),您需要评估(也许详尽测试)不仅gcc
和make
,而且还bison
。这是工程原因,而不是科学原因。请注意,某些嵌入式系统可能会使用随机算法,特别是为了巧妙地处理噪声。输入信号(可能是由于稀有的宇宙射线而导致的甚至随机位翻转)。证明,测试或分析(或只是评估)此类基于随机的算法是一个非常困难的话题。
还查看Frama-Clang和CompCert,并注意以下几点:
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 ++太空软件中的任何运行时错误都可能使任务崩溃(请再次阅读有关阿丽亚娜5首次飞行失败的信息-用Ada的某些方言编码,当时该词具有“更好的”比“今天的C ++ 17”更“安全”的类型系统),但不要对欧洲人笑得太多。架带有其MACS的波音737 MAX的类似情况)。
我个人的建议(但请不要太在意。在2019年,它比其他任何事情都更容易理解)将是考虑使用Rust编写您的太空嵌入式软件。因为它比C ++更安全。当然,您将需要在5到7年内花费5到1000万欧元(或MUS $),以获得适用于太空计算机的优质Rust编译器(同样,如果您有能力花费,请与我专业联系)免费软件Compcert / Rust之类的编译器)。但这只是软件工程和软件项目管理的问题(有关更多信息,请阅读《神话般的月刊》和《胡说八道》,也请注意迪尔伯特原理。:它适用于太空软件行业或嵌入式编译器行业,以及其他任何方面。
我的强烈个人观点是,欧盟委员会应资助(例如通过Horizon Europe)类似项目的免费软件CompCert ++(或更好的是Compcert / Rust),而此类项目将需要5年以上且5次以上级博士研究人员)。但是,在60岁那年,我很遗憾地知道这将不会发生(因为EC意识形态-主要是出于明显的原因而受到德国政策的启发-仍然是“历史终结”的幻象,因此H2020和Horizon Europe在实践中,主要是通过欧洲避税天堂为欧洲公司实施税收优化的方法,并且在与CompCert项目的几个成员进行了几次私下讨论之后。我很遗憾地期望DARPA或NASA更有可能资助某些未来的CompCert / Rust项目(比EC资助)。
注意 欧洲航空电子业(主要是空中客车公司)正在使用比北美航空(波音公司)更为正式的方法。因此一些(不是全部)被避免单元测试(因为替换形式证明的源代码,或许与像工具邮资-C或ASTREE -既不是已认证的C ++,只对一个子集的C禁止时的动态存储器分配和几个C的其他功能)。这是由DO-178C允许(而不是先前的DO-178B)并由法国监管机构DGAC批准(我猜是由其他欧洲监管机构批准)。
另请注意,许多SIGPLAN会议与OP的问题间接相关。
std::map<std::string,long>
,这令人怀疑,然后您出于动态分配的原因而不是因为它是模板而反对它。我猜您想对动态分配进行详细介绍,因为OP在介绍了代码膨胀的模板之后也提到了动态分配,这是使验证变得更加困难的一般复杂性的一部分。它可以安全地使用模板,如果你认为你在做什么,但肯定很容易得到代码膨胀。
反对在安全代码中使用模板的观点是,认为模板会增加代码的复杂性而没有真正的好处。如果您使用的工具不好并且有经典的安全性概念,则此论点是有效的。请看以下示例:
template<class T> fun(T t){
do_some_thing(t);
}
用经典的方式来指定安全系统,您必须提供代码的每个功能和结构的完整描述。这意味着没有规范就不允许有任何代码。这意味着您必须以常规形式完整描述模板的功能。由于明显的原因,这是不可能的。顺便说一句,同样的原因也禁止类似函数的宏。如果您以描述此模板的所有实际实例的方式改变了想法,则可以克服此限制,但是您需要适当的工具来证明您确实描述了所有模板。
第二个问题是:
fun(b);
这条线不是独立的线。您需要查找b的类型以知道实际调用了哪个函数。理解模板的正确工具在这里有帮助。但是在这种情况下,确实使手动检查代码变得更加困难。
在我看来,有关模板是导致漏洞的原因的说法似乎完全是超现实的。主要有两个原因:
模板被“编译掉”,即像任何其他函数/成员一样被实例化和代码生成,并且没有特定于它们的行为。就像它们从未存在过一样;
任何语言的建筑都不是安全或脆弱的;如果电离粒子更改了单个内存(无论是代码还是数据),一切皆有可能(从无明显问题到处理器崩溃)。屏蔽系统的方法是添加硬件内存错误检测/纠正功能。不能通过修改代码!