在C语言中使用realloc函数

3
我正在使用void *realloc(void *pointer, size_t size);来增加指针的大小。realloc是如何工作的?它会创建一个新的地址空间,将旧值复制到新地址空间并返回该地址的指针吗?还是只是分配更多的内存并将其绑定到旧内存上?

3
你可以轻松地在 man 手册中找到答案。 - Kylo
可能是理解Realloc的重复问题。 - Jens Gustedt
5个回答

5
@Iraklis 给出了正确的答案:如果可以,它会执行第二个(更改内存大小),否则执行第一个(重新分配内存)。但是有时候无法执行这两个操作,会导致失败。请注意,如果无法重新分配内存,则会返回 NULL,但是内存不会被释放。以下代码是错误的:
ptr = realloc(ptr, size);

如果realloc返回NULL,旧的ptr将永远不会被释放,因为你已经用NULL覆盖了它。要正确地执行此操作,您必须执行以下操作:

void *tmp = realloc(ptr, size);
if(tmp) ptr = tmp;
else /* handle error, often with: */ free(ptr);

在BSD系统中,上述内容被转化为一个名为reallocf的库函数,其实现方式如下:
void *reallocf(void *p, size_t s)
{
    void *tmp = realloc(p, s);
    if(tmp) return tmp;
    free(p);
    return NULL;
}

让您安全使用:

ptr = reallocf(ptr, size);

请注意,如果realloc需要分配新空间并复制旧数据,则它将释放旧数据。只有在无法调整大小时,它才会保持您的数据完好无损,以防调整大小失败是可恢复错误的情况下。

如果接下来是if( !ptr ) fatal_error();,那么ptr = realloc(ptr, size);并不错。其他情况非常罕见。当然,如果您尝试通过释放现有数据(例如弱指针)来从OOM中恢复,那么使用ptr=是相当糟糕的。道德准则是,您永远不应该调用普通的mallocrealloc,而是只使用包装版本,这些版本可能会尝试恢复内存并在无法分配内存时死亡或抛出异常(C中的longjmp)。当然,如果在C++中编程,应该使用new,或者更好地使用STL。 - Jim Balter
@Jim - 不一定。如果你有一个需要调整内部大小的数组或字符串库(使用普通C语言),那么这个库不应该因为无法适当地调整缓冲区大小而死亡,但也不应该期望它抛弃所有现有数据。 - Chris Lutz
我认为reallocf的实现有问题,特别是当p可能为NULL时。如果tmp == NULL,你会释放一个NULL指针。 - khatchad
1
@RaffiKhatchadourian free(NULL)什么也不做,完全安全。 - Chris Lutz

3

这要看情况!如果无法在原地调整内存区域的大小,则会分配一个新的内存区域,复制旧数据并释放旧内存。


2
您误用了“地址空间”的术语。您进程中的所有内存都存在于一个单独的地址空间中。未被程序、全局变量和堆栈使用的内存称为“堆”。mallocrealloccalloc只是malloc并清除)从堆中分配内存。大多数realloc的实现将检查是否有足够(size字节)的自由空间从pointer(必须指向先前由mallocrealloc分配的块 - realloc知道该块有多大)开始,并且如果有,只需增加在pointer给出的位置分配的块的大小并返回,而无需复制。如果没有足够的空间,则会执行等价于newptr = malloc(size); memcpy(newptr, pointer, size_of_old_block); free(pointer); return newptr;...也就是说,它将分配一个足以容纳size字节的块,将pointer处的数据复制到该块中,释放旧块,并返回新块的地址。

0

我认为答案取决于所请求的大小和可用堆空间。

从程序员的角度来看,我认为我们能够得到的保证就是如果新的分配成功,指针将不为空。因此,尽管它现在指向由size_t表示的更大的内存块,但指针可能仍然保持不变。


0

Realloc函数不会改变指针的大小,因为在同一架构下指针的大小始终相同。它会改变指针所指向的已分配内存的大小。其工作原理在此处描述:http://msdn.microsoft.com/en-us/library/xbebcx7d.aspx。简而言之,是的,它会分配更多的内存,但不会改变您的内容;如果必须移动内存,则会复制内容。当然,您可以指定较短的大小,在这种情况下,它会修剪已分配的内存,同样不会影响内容。


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