如果所指向的区域被移动,将执行 free(ptr)。请问能否解释一下关于 realloc() 的上述语句?这条语句来自于 calloc、malloc、realloc 和 free 的手册页。
我认为以下解释可能更清晰:
如果当前块的扩展需要更多空间而该空间不足,那么将分配一个新块,其大小与所需相同,并将现有数据从旧块复制到新块的开头。然后释放旧块并返回一个指向新块的指针。
参考自C语言中的realloc
假设你有以下堆布局。这是一个简化的内存分配器,其中堆中没有控制信息占用空间。
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处)的内容复制到其中。然后它会给您这个新块的地址并释放旧块,因为您不再需要它了。 这就是你问题中提到的那句话的意思。
移动缓冲区的这种操作取决于内存分配策略,但通常情况下,如果:
则缓冲区不会被移动(这通常很昂贵,因为它涉及大量的内存复制)。
您不能总是在原地扩展内存区域。堆中可能没有足够的空间。因此,它将分配一个全新的内存块并释放旧的内存,而不是扩展它。