bison
(或RPCGEN)(由make
和gcc
编译),则需要评估(并可能详尽测试)的不仅是gcc
和make
,还有bison
。这是一个工程原因,而不是科学原因。请注意,一些嵌入式系统可能会使用随机算法,特别是巧妙地处理嘈杂输入信号(甚至是由于足够罕见的宇宙射线引起的随机位翻转)。证明、测试或分析(或只是评估)这样基于随机的算法是一个非常困难的话题。C++11(或更高版本)是一种极其复杂的编程语言,它没有完整的正式语义。在C++方面足够专业的人只有全球几十个(可能大部分都在其标准委员会中)。我能够编写C++代码,但不能解释所有移动语义的微妙角落,或者C++ 内存模型。此外,C++实际上需要使用许多优化才能有效地运行。
制作无错误的C++编译器非常困难,尤其是因为C++实际上需要棘手的优化,以及C++规范的复杂性。但目前的编译器(如最新的GCC或Clang)实际上相当不错,并且它们只有少量(但仍然存在)残留的编译器错误。目前还没有CompCert ++用于C ++,而制作一个需要数百万欧元或美元(但如果您能够筹集这样的金额,请通过电子邮件与我联系,例如发送到basile.starynkevitch@cea.fr
,我的工作电子邮件)。而航天软件行业则非常保守。
制作好的C或C ++堆内存分配器很困难。编写一个是一种权衡。开个玩笑,可以考虑将此C堆内存分配器适应于C++。
证明模板相关的C ++代码的安全属性(特别是缺少运行时竞争条件或未定义行为,如缓冲区溢出)在2019年第二季度仍略领先于C ++代码的静态程序分析技术。我的Bismon技术报告草案(这是一份H2020可交付成果的草案,请跳过欧洲官僚的页面)有几页详细解释了这一点。请注意Rice定理。
整个系统的C ++嵌入式软件测试可能需要进行火箭发射(像阿丽亚娜5号501试飞那样),或者至少需要在实验室中进行复杂而繁重的实验。它非常昂贵。即使在地球上测试火星车也需要花费大量的资金。
std::map<std::string,long>
。在内存不足的情况下会发生什么?你如何“证明”,或者至少“说服”,资助一个1亿欧元太空火箭的组织中的工作人员,你的嵌入式软件(包括用于构建它的编译器)已经足够好了?十年前的规定是禁止任何形式的动态堆分配。
即使这些很难被证明,或者更普遍地评估它们的质量(你可能想在其中使用自己的分配器)。在空间中,代码空间是一个强约束条件。因此,您将使用例如我所说的不是复杂的标准库内容,而是特别制作的自定义模板。
g++ -Os -Wall
或clang++ -Os -Wall
进行编译。但是,您如何证明或者仅仅测试所有由-Os
完成的微妙优化(这些是特定于您的GCC或Clang版本的)?您的空间资助组织会问您这个问题,因为嵌入式C++空间软件中的任何运行时错误都可能导致任务崩溃(再次阅读Ariane 5首飞失败-当时编码使用的是某种Ada方言,其类型系统比今天的C++17“更好”和“更安全”),但不要对欧洲人笑得太多。波音737 MAX与其MACS是一个类似的混乱。
我的个人建议(但请不要太认真对待)是考虑使用Rust来编写您的嵌入式软件,因为它比C ++稍微安全一些。当然,您必须花费5至10 M€(或MUS $)在5或7年内获得适用于航天计算机的良好Rust编译器(如果您有能力在自由软件Compcert / Rust上花费如此多的话,请与我联系)。但这只是软件工程和软件项目管理的问题(阅读神话般的程序员月份和胡说八道的工作以获取更多信息,还要注意Dilbert principle:它同样适用于航天软件行业或嵌入式编译器行业,也适用于其他任何行业)。
我强烈而个人地认为,欧洲委员会应该通过Horizon Europe等方式资助一个自由软件CompCert++(甚至更好的是Compcert/Rust)项目(这样的项目需要超过5年时间和超过5名顶尖的博士研究人员)。但是,我60岁时很遗憾地知道这不会发生(因为欧盟委员会的意识形态 - 主要受德国政策的明显影响 - 仍然是历史终结的幻觉,因此H2020和Horizon Europe在实践中主要是通过欧洲避税天堂为企业实施税收优化的途径),这是在与CompCert项目的几位成员私下讨论后得出的结论。我很遗憾地预计,DARPA或NASA更有可能资助未来的CompCert/Rust项目(而不是欧盟资助它)。std::map<std::string,long>
,然后你反对它的动态分配原因,而不是因为它是一个模板,这让我感到有些可疑。我猜你想详细说明动态分配,因为OP也在提及它,之前已经涉及了代码膨胀和作为导致验证难度加大的一般复杂性的模板。如果你考虑清楚你要做什么,使用模板是安全的,但肯定容易出现代码膨胀。 - Peter Cordes反对在安全代码中使用模板的论点是,它们被认为会增加代码的复杂性而没有真正的好处。如果你使用的工具不好,或者有一个传统的安全理念,这个论点是有效的。请看以下例子:
template<class T> fun(T t){
do_some_thing(t);
}
fun(b);
这一行不是一个独立的行。您需要查找b的类型,才能知道实际调用的函数。理解模板的适当工具可以帮助解决这个问题。但在这种情况下,手动检查代码确实变得更加困难。
我对模板被视为漏洞的说法感到非常不可思议,主要有两个原因:
模板被“编译消除”,即像其他函数/成员一样实例化和代码生成,并且没有特定于它们的行为。就像它们从未存在一样;
任何语言中的构造都不是安全或易受攻击的;如果电离粒子更改了内存的单个位(无论是在代码还是数据中),则任何事情都有可能发生(从没有注意到的问题发生到处理器崩溃的情况)。保护系统免受此类攻击的方法是添加硬件内存错误检测/纠正功能,而不是修改代码!