使用realloc重新调整缓冲区大小

4
如果所指向的区域被移动,将执行 free(ptr)。请问能否解释一下关于 realloc() 的上述语句?这条语句来自于 calloc、malloc、realloc 和 free 的手册页。
3个回答

16

我认为以下解释可能更清晰:

如果当前块的扩展需要更多空间而该空间不足,那么将分配一个新块,其大小与所需相同,并将现有数据从旧块复制到新块的开头。然后释放旧块并返回一个指向新块的指针。

参考自C语言中的realloc


11

假设你有以下堆布局。这是一个简化的内存分配器,其中堆中没有控制信息占用空间。

Addr       A                   B
     +------------+      +------------+
1000 | your space |      | your space |
     +------------+      +------------+
2000 | free space |      | used space |          
     |            |      +------------+
3000 |            |      | free space |
     |            |      |            |
4000 |            |      |            |
     +------------+      +------------+

在这两种情况下,你都在地址1000分配了1000个字节的内存。但是,在情况B中,紧随其后的内存被分配给了其他用途。

现在让我们来看看当你想将内存重新分配为2000个字节时会发生什么。

在情况A下,这很容易,它只是按照下面的图表扩大你的分配。

但是,在情况B下,就不那么容易了。紧随你的块之后的内存正在使用中,因此没有足够的空间来扩展你的分配,而你需要连续的内存。以下是两种情况的结束位置:

Addr       A                   B
     +------------+      +------------+
1000 | your space |      | free space |
     |            |      +------------+
2000 |            |      | used space |
     +------------+      +------------+
3000 | free space |      | your space |
     |            |      |            |
4000 |            |      |            |
     +------------+      +------------+

对于情况B,分配器找到一个足够大的块(在3000处),可以用来满足您所需的扩展,并将您当前块(在1000处)的内容复制到其中。然后它会给您这个新块的地址并释放旧块,因为您不再需要它了。 这就是你问题中提到的那句话的意思。

移动缓冲区的这种操作取决于内存分配策略,但通常情况下,如果:

  • 它后面有空闲空间,加上当前空间可以满足重新分配;或者
  • 您正在减少大小。

则缓冲区不会被移动(这通常很昂贵,因为它涉及大量的内存复制)。


你需要澄清使用了额外空间的“其他人”是指“分配空间的程序的另一个部分”,而不是“由另一个用户运行的另一个进程”吗? - Jonathan Leffler

2

您不能总是在原地扩展内存区域。堆中可能没有足够的空间。因此,它将分配一个全新的内存块并释放旧的内存,而不是扩展它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接