安全关键项目中动态分配的替代方案 (C)
Posted
技术标签:
【中文标题】安全关键项目中动态分配的替代方案 (C)【英文标题】:Alternatives to dynamic allocations in safety critical projects (C) 【发布时间】:2016-08-05 17:00:27 【问题描述】:安全关键项目不建议进行任何动态分配或释放分配的内存。只有在程序执行的细化/初始化阶段,它才被允许。
我知道你们中的大多数人会争辩说,要实现 SW,它应该只执行所有静态分配,或者在代码中做一些理由,即动态分配不会损害整个程序等,但是,还有其他选择吗?问题?是否有任何方法或示例可以在程序初始化/细化期间分配一些(堆)内存并从那里分配/释放内存?或者如果我们真的想要在(安全关键的)项目中进行动态分配,这个问题的任何解决方案/替代方案?
【问题讨论】:
【参考方案1】:这类问题最常由希望能够在安全相关系统中使用动态内存分配而没有“过度”限制的开发人员提出 - 这通常意味着他们不会被阻止动态分配内存他们选择的数量,他们选择的时间,以及(可能)在他们选择时释放该内存。
我将首先解决这个问题(动态内存分配可以在没有限制的关键系统中使用吗?)。然后我将回到涉及接受一些关于如何(何时或是否)使用动态内存分配的限制的选项。
在“安全关键项目”中,这样的事情通常是不可能的。安全相关系统通常具有与减轻或消除特定危害有关的强制性要求。未能充分减轻或消除特定危害(即满足要求)可能会导致伤害 - 例如,人员死亡或受伤。在这样的系统中,通常有必要在一定程度上严格确定危害是否得到适当和可靠的减轻或消除。其结果通常是一组与确定性相关的要求 - 通过适当的分析确定系统以指定方式完成操作的能力 - 其中行为和时间等属性被严格指定。
如果没有限制地使用动态内存分配,则很难确定系统的某些部分是否按要求运行。问题类型包括;
未分配内存的碎片。 无法确保分配 N 个连续字节内存的请求会成功,即使 N 字节内存可用。如果之前以任意顺序进行了多次分配和解除分配,则尤其如此 - 即使 N 字节的内存可用,它们也可能不在一个连续的包中。 充分性。通常很难保证必须成功的关键内存分配确实成功了。 适当的释放。很难防止在仍然需要内存时释放内存(导致访问已被释放的内存的可能性)或确保实际释放不再需要的内存(例如阻止内存泄漏)。 及时性。 缓解上述问题的尝试意味着分配或解除分配的时间是可变的、不可预测的,并且可能没有上限。处理这些问题的方法的示例是碎片整理(处理碎片问题)或垃圾收集(处理充分性和/或适当释放的问题)。这些过程需要时间和其他系统资源。如果它们在尝试分配时完成,分配内存的时间将变得不可预测。如果它们是在释放内存时完成的,那么释放内存的时间就变得不可预测。如果它们在其他时间完成,其他可能很关键的代码的行为可能会变得不可预测(例如,应用程序的世界实际上冻结了)。所有这些因素,以及更多因素,意味着不受限制的动态内存分配在系统的时间确定性或资源使用的要求范围内不能很好地工作。本质上,系统要求需要施加一些限制,并根据系统强制执行。
如果对动态内存分配的限制是可以接受的,有一些选择。一般来说,这些技术需要政策约束和技术解决方案方面的支持,以鼓励(最好是在高关键性系统中强制执行)遵守这些政策。政策执行可能是技术性的(例如自动和手动设计和代码审查、定制的开发环境、合规性测试等)或组织性的(例如解雇故意围绕关键政策工作的开发人员)。
技术示例包括:
根本没有动态分配。即只有静态分配。 仅在系统初始化期间使用动态内存分配。这需要提前确定需要分配的最大内存量。如果内存分配失败,则将其视为任何 POST(开机自检)失败。 分配内存,但从不释放它。这往往可以避免碎片问题,但可能会使确定系统需要多少内存的上限变得更加困难。 自定义分配。系统(或应用程序)显式管理动态内存分配,而不是使用通用库函数(例如与所选编程语言相关联的函数)。这通常意味着引入自定义分配器并禁止(或禁用)使用通用库函数进行动态内存管理。自定义分配器的设计必须明确考虑到特定系统的需求。 内存管理中的装箱。这是一种特殊类型的自定义分配,应用程序分配一个内存池,并且函数从池中请求固定数量(或固定数量的倍数)。因为内存池是由应用程序固定的,所以应用程序会监控内存池中有多少内存在使用中,如果内存用完,就会采取行动释放内存。池中的分配和解除分配也可以以可预测的方式执行(因为正在管理与动态内存分配有关的一些更普遍的问题)。关键系统可能有多个池,每个池供特定功能集使用。 分区。明确阻止非关键函数访问已建立供关键函数使用的内存池。这可以确保关键功能可以访问他们需要的内存,并且还有助于确保低关键功能的故障不会触发高关键功能的故障。分区可以在应用程序中执行,也可以在(经过适当认证的)主机操作系统中执行,或两者兼而有之......取决于系统的需要。其中一些方法可以相互支持。
【讨论】:
谢谢你这么好的描述,包括典型问题列表和典型解决方案列表。对于后者,我将添加另一个:实施诊断,即上面列表中的错误之一已发生。最典型的例子可能是在分配之前(或之后)检查分配水印:如果软件耗尽堆内存,则强制系统进入其安全状态。以上是关于安全关键项目中动态分配的替代方案 (C)的主要内容,如果未能解决你的问题,请参考以下文章