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

Aka*_*kay 5 safety-critical dynamic-allocation memory-safety

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

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

Pet*_*ter 11

想要能够在安全相关系统中使用动态内存分配而没有"过度"限制的开发人员最常询问这类问题 - 这通常意味着他们不会被阻止以他们选择的数量动态分配内存,当他们选择时,并且(可能)在他们选择时释放那些记忆.

我将解决这个问题(动态内存分配是否可以在一个没有限制的关键系统中使用?).然后我将回到涉及接受对动态内存分配如何(何时或如果)使用的一些限制的选项.

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

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

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

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

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

技术的例子包括:

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

其中一些方法可用于相互支持.