在开发一款嵌入式系统软件时,我多次使用realloc()函数。现在有人说我“不应该在嵌入式系统中使用realloc()”,但没有任何解释。
realloc()对嵌入式系统是危险的吗?为什么?
发布于 2011-08-25 17:43:57
是的,所有的动态内存分配都被认为是危险的,而且它在大多数“高完整性”嵌入式系统中都是被禁止的,例如工业/汽车/航空航天/医疗技术等。
它在高完整性嵌入式系统中被禁止的原因不仅是潜在的内存泄漏,而且还有许多与这些函数相关的危险的未定义/未指定/隐式定义的行为。
编辑:我还忘了提到堆碎片,这是另一个危险。此外,MISRA-C还提到“数据不一致,内存耗尽,不确定行为”作为不应该使用它的原因。前两种看起来相当主观,但在这种类型的系统中,非确定性行为肯定是不允许的。
参考文献:
发布于 2011-08-25 17:35:22
这取决于特定的嵌入式系统。在小型嵌入式系统上进行动态内存管理从一开始就很棘手,但realloc并不比free和malloc更复杂(当然,这不是它所做的事情)。在某些嵌入式系统中,您从一开始就做梦也想不到调用malloc。在其他嵌入式系统上,您几乎可以假装它是台式机。
如果您的嵌入式系统的分配器很差,或者内存不多,那么realloc可能会导致碎片问题。这就是为什么你也避免使用malloc,因为它会导致同样的问题。
另一个原因是一些嵌入式系统对可靠性要求很高,malloc / realloc可以返回NULL。在这些情况下,所有内存都是静态分配的。
发布于 2011-08-27 05:40:47
在许多嵌入式系统中,自定义内存管理器可以提供比malloc/realloc/free更好的语义。例如,一些应用程序可以使用一个简单的标记和释放分配器。将指针指向尚未分配的内存的起始处,通过向上移动指针来分配内容,并通过将指针移动到它们下面来丢弃它们。如果有必要丢弃一些东西,同时保留在它们之后分配的其他东西,那么这将不起作用,但在没有必要的情况下,标记并释放分配器比任何其他分配方法都更便宜。在标记和释放分配器不够好的情况下,从堆的开始分配一些东西,从堆的末尾分配其他东西可能会很有帮助;可以释放从一端分配的东西,而不影响从另一端分配的东西。
有时在非多任务或协作多任务系统中有用的另一种方法是使用内存句柄而不是直接指针。在典型的基于句柄的系统中,有一个包含所有已分配对象的表,该表在内存顶部向下工作,对象本身是自下而上分配的。内存中的每个已分配对象要么包含对引用它的表槽的引用(如果是活动的),要么包含对其大小的指示(如果是死的)。每个对象的表项将保存对象的大小以及指向内存中对象的指针。只需找到一个空闲的表槽(很容易,因为表槽的大小都是固定的),在空闲内存的起始处存储对象的表槽的地址,在此之后存储对象本身,并将空闲内存的起始点更新为恰好指向该对象,就可以分配对象。可以通过用长度指示替换反向引用并释放表中的对象来释放对象。如果分配失败,则从内存顶部开始重新定位所有活动对象,覆盖所有已死对象,并更新对象表以指向它们的新地址。
这种方法的性能是不确定的,但碎片不是问题。此外,在一些协作的多任务系统中,可能会“在后台”执行垃圾收集;如果垃圾收集器能够在通过空闲空间所需的时间内完成一次遍历,就可以避免长时间的等待。此外,可以使用一些相当简单的“世代”逻辑来提高平均情况下的性能,但代价是最坏情况下的性能。
https://stackoverflow.com/questions/7188040
复制相似问题