安全关键项目中动态分配的替代方案(C)

时间:2016-04-14 08:49:39

标签: dynamic-allocation safety-critical memory-safety

安全关键项目不建议任何动态分配或释放分配的内存。仅在程序执行的精化/初始化阶段,才允许。

我知道你们中的大多数人都会争论实施SW,它应该只进行所有静态分配,或者在代码中做一些理由,动态分配不会损害整个程序等等但是,还有什么替代方案问题?有什么方法或任何例子可以在程序初始化/详细说明期间分配一些(堆)内存并从那里分配/释放内存?如果我们真的想在(安全关键)项目中进行动态分配,还是解决这个问题的任何解决方案/替代方案?

1 个答案:

答案 0 :(得分:11)

这种类型的问题最常由想要能够在安全相关系统中使用动态内存分配的开发人员提出,而不需要过多的问题。限制 - 这通常意味着它们不会被阻止以他们选择的数量动态分配内存,当他们选择时,以及(可能)在他们选择时释放内存。

我将首先解决这个问题(动态内存分配是否可以在关键系统中无限制地使用?)。然后,我将回到选项,包括接受对动态内存分配的使用方式(何时或如果)的一些限制。

在一个"安全关键项目"中,这种事情通常是不可能的。安全相关系统通常具有与减轻或消除特定危险有关的强制性要求。未能充分减轻或消除特定危害(即满足要求)可能导致伤害 - 例如,人员死亡或受伤。在这样的系统中,通常需要在某种程度上严格地确定危险被适当且可靠地减轻或消除。其结果通常是与确定性相关的一组要求 - 通过适当的分析确定系统以特定方式完成操作的能力 - 其中行为和时间等属性被严格规定。

如果使用动态内存分配而没有限制,则很难确定系统的某些部分是否按要求运行。问题类型包括;

  • 未分配内存的碎片。即使有N个字节的内存可用,也无法确保分配N个连续字节内存的请求成功。如果先前有任意顺序的多个分配和解除分配,则尤其如此 - 即使N个字节的内存可用,它们也可能不在连续的包中。
  • 充足。通常很难确保必须成功的关键内存分配确实成功。
  • 适当的发布。很难阻止内存在仍然需要时被释放(导致可能访问已经解除分配的内存)或确保不再需要的内存实际被释放(例如防止内存泄漏)。
  • 及时性。尝试缓解上述问题意味着分配或解除分配的时间是可变的,不可预测的,可能没有上限。处理这些问题的方法的示例是碎片整理(以处理碎片问题)或垃圾收集(以处理充分性和/或适当释放的问题)。这些过程需要时间和其他系统资源。如果在尝试分配时完成它们,则分配内存的时间变得不可预测。如果它们在释放内存时完成,则释放内存的时间变得不可预测。如果它们在其他时间完成,其他 - 可能是关键的 - 代码的行为可能变得不可预测(例如,世界有效地冻结了应用程序)。

所有这些因素以及更多因素意味着无限制的动态内存分配在系统的定时或资源使用的确定性要求中不能很好地工作。本质上,系统要求需要施加一些限制,并且根据系统的不同,强制执行。

如果可以接受对动态内存分配的限制,可以选择。通常,这些技术需要在政策约束和技术解决方案方面提供支持,以鼓励(优选地在高关键性系统中强制执行)遵守这些策略。策略执行可能是技术性的(例如自动和手动设计和代码审查,定制的开发环境,合规性测试等)或组织(例如,解雇那些故意围绕关键策略工作的开发人员)。

技术示例包括;

  • 根本没有动态分配。即仅限静态分配。
  • 仅在系统初始化期间使用动态内存分配。这需要提前确定需要分配的最大内存量。如果内存分配失败,请将其视为任何POST(开机自检)失败。
  • 分配内存但永远不会释放它。这有助于避免碎片问题,但可能会更难以确定系统需要多少内存的上限。
  • 自定义分配。系统(或应用程序)显式地管理动态内存分配,而不是使用通用库函数(例如,与所选编程语言相关联的函数)。这通常意味着引入自定义分配器并禁止(或禁用)使用通用库函数进行动态内存管理。必须根据特定系统的需要明确设计自定义分配器。
  • 在内存管理中装箱。这是一种特殊类型的自定义分配,其中应用程序分配一个内存池,并且函数从池中请求固定金额(或固定金额的倍数)。由于应用程序已修复池,因此应用程序将监视池中正在使用的内存量,并在内存耗尽时采取措施释放内存。池中的分配和解除分配也可以可预测地执行(因为正在管理动态内存分配的一些更普遍的问题)。关键系统可能有多个池,每个池都由特定的功能集独占使用。
  • 分区。明确阻止非关键功能访问已为关键功能使用而建立的内存池。这样可以确保关键功能可以访问所需的内存,还有助于确保低临界功能的故障不会触发高临界功能的故障。分区可以在应用程序内执行,也可以在(经过适当认证的)主机操作系统内执行,或者根据系统的需要执行....

其中一些方法可以互相支持。