在开发嵌入式系统软件时,我经常使用realloc()
函数。现在有人告诉我在嵌入式系统中“不应该使用realloc()
”,但没有任何解释。
realloc()
在嵌入式系统中是否有危险?为什么?
在开发嵌入式系统软件时,我经常使用realloc()
函数。现在有人告诉我在嵌入式系统中“不应该使用realloc()
”,但没有任何解释。
realloc()
在嵌入式系统中是否有危险?为什么?
是的,所有动态内存分配都被视为危险,并且被大多数“高完整性”嵌入式系统禁止使用,例如工业/汽车/航空/医疗技术等等。您的问题的答案取决于您正在进行哪种类型的嵌入式系统。
它被禁用于高完整性嵌入式系统的原因不仅在于潜在的内存泄漏,还有许多与这些函数相关的危险未定义/未规定/实现定义行为。
编辑:我还忘记提到堆片段化,这也是一个危险。此外,MISRA-C 还提到“数据不一致、内存耗尽、非确定性行为”作为不能使用它的理由。前两个似乎相当主观,但非确定性行为绝对是这类系统不允许的。
参考文献:
realloc
并不比 free
和 malloc
(当然,它并不是做这个的)更加复杂。在有些嵌入式系统上,你甚至不会想到首先调用 malloc
。在其他嵌入式系统上,你几乎可以把它当作桌面。realloc
可能会导致碎片化问题。这也是为什么你要避免使用 malloc
,因为它会引起同样的问题。malloc
/ realloc
可能会返回 NULL
。在这些情况下,所有内存都是静态分配的。realloc
可能失败,就像 malloc
一样。这就是为什么在嵌入式系统中可能不应该使用它们的原因之一。
realloc
比 malloc
更糟糕,因为您需要在 realloc
过程中保证旧指针和新指针都有效。换句话说,在原始的 malloc
空间大小的基础上,您需要两倍的内存空间,再加上任何额外的量(假设 realloc
增加了缓冲区的大小)。
使用 realloc
会非常危险,因为它可能会返回您内存位置的新指针。这意味着:
realloc
后都必须更正。realloc
必须是原子的。如果您禁用中断以实现此目的,则 realloc
的时间可能足够长,以至于看门狗会导致硬件重置。更新:我只是想让它更清楚。我并不是说 realloc
比使用 malloc
/free
实现 realloc
更糟糕。那也同样糟糕。如果您可以进行单个的 malloc
和 free
,而不需要调整大小,那就稍微好一些,但仍然很危险。
malloc()
/free()
? - sharptooth在嵌入式系统中,realloc() 的问题与任何其他系统中的问题并无不同,但在内存更为受限、失败后果更难以接受的系统中,其后果可能更加严重。
到目前为止未提及的一个问题是,realloc()(以及任何其他动态内存操作)是非确定性的;也就是说,它的执行时间是可变和不可预测的。许多嵌入式系统也是实时系统,在这样的系统中,非确定性行为是不可接受的。
另一个问题是线程安全性。请检查您的库文档,以了解您的库是否对动态内存分配进行了线程安全处理。通常情况下,如果是这样,您将需要实现互斥体存根,以将其与特定的线程库或RTOS集成。
并非所有的嵌入式系统都是相同的;如果您的嵌入式系统不是实时的(或者所涉及的进程/任务/线程不是实时元素的一部分,并且有大量未使用的内存或虚拟内存功能),那么在大多数情况下,使用realloc()可能是可以接受的,尽管这样做可能不明智。
与其接受“常规智慧”并禁止动态内存,不如了解您的系统要求和动态内存函数的行为,并做出适当的决策。话虽如此,如果您正在构建可重用性和可移植性尽可能广泛的平台和应用程序的代码,则重新分配可能是一个非常糟糕的想法。例如,不要将其隐藏在库中。
还要注意,C++ STL容器类存在相同的问题,即在增加容器容量时动态重新分配和复制数据。
如果可能的话,最好避免使用realloc,因为这个操作很耗费资源,特别是放在循环中:例如,如果需要扩展一些已分配的内存,并且当前块后面没有间隙与下一个已分配的块之间 - 这个操作几乎等同于:malloc + memcopy + free。
realloc()
比 malloc()
/free()
差吗? - sharptoothrealloc
永远不应该比malloc
/memcpy
/free
更差,因为它总是可以只是做那个操作,并且可能会避免memcpy
。 - Dietrich Epp
realloc()
而不是malloc()
或alloca()
?我记得曾经在一本书中看到过对realloc()
进行批评,因为它的行为高度重载,但我并不完全赞同这种观点,如果有人因此禁止使用它,我会感到失望。 - sh1