realloc()在失败并返回NULL时的正确使用方法是什么?

17

有人能总结一下realloc()的正确用法吗?

如果realloc()失败了怎么办?

从我目前看到的情况来看,似乎如果realloc()失败了,你必须free()旧指针。是这样吗?

这里有一个例子:

   1.  char *ptr = malloc(sizeof(*ptr) * 50);
   2.  ...
   3.  char *new_ptr = realloc(ptr, sizeof(*new_ptr) * 60);
   4.  if (!new_ptr) {
   5.      free(ptr);
   6.      return NULL;
   7.  }

假设第3行的realloc()失败了,那么第5行通过free()释放ptr是正确的吗?


1
你那里的代码看起来不错,只要你确认了原始的malloc操作成功了。 - Robert Groves
实际上,即使原始的malloc()失败了,realloc()对于其第一个参数为空指针也没有问题 - 它会表现得像malloc()一样,并且(在此上下文中)可能也会失败(因为如果malloc()无法分配50个字节,则realloc()可能也无法分配60个字节)。 - Jonathan Leffler
4个回答

22

http://www.c-faq.com/malloc/realloc.html

如果realloc无法找到足够的空间,则返回空指针,并保留之前分配的内存。

因此,您确实需要仍然释放先前分配的内存。


1

这取决于你想做什么。当realloc失败时,你想做什么:释放旧块还是保持它不变?如果你想释放它,那就释放它。

还要记住,在C89/90中,如果你使用零目标大小进行realloc请求,realloc函数可能会返回空指针,即使原始内存已成功释放。这是C89/90的一个缺陷,因为无法通过空返回来区分成功和失败。

在C99中,这个缺陷被修复了,并且保证了空返回与重新分配的成功/失败之间的严格关系。在C99中,空返回总是意味着realloc的完全失败。


我找不到你所声称存在的要求。你能提供引用吗? - R.. GitHub STOP HELPING ICE
@R..:realloc 不能像 free 一样使用,因为 realloc 必须返回某些东西,即使 C89/90 允许非零返回。这就是为什么实际上大小为 0 的 realloc 总是像 free 一样运行,然后是 malloc(0)。C89/90 简单地未能正确描述此行为,并且因此可能未能提供可靠的故障检测方法的原因。 - AnT stands with Russia
POSIX 要求realloc 在目标大小为0时扮演 free 的角色,所以它肯定可以。请参考http://www.opengroup.org/onlinepubs/9699919799/functions/realloc.html。 - R.. GitHub STOP HELPING ICE
realloc 只有在原始对象未被释放时才可以返回 0 的假定要求。 - R.. GitHub STOP HELPING ICE
@R..:在C99中明确规定了“空返回表示失败”的要求。此外,您可能还想查看“C99的基本原理”(http://www.open-std.org/jtc1/sc22/wg14/www/C99RationaleV5.10.pdf),其中他们解释了为什么`realloc`的规范会发生如此大的变化:为了允许希望返回非空零大小分配请求的实现。显然,这样的实现是存在的。 - AnT stands with Russia
显示剩余20条评论

0
如果realloc失败,我认为您不会想删除原始块,因为这样会丢失它。似乎realloc将调整旧块的大小(或返回指向新位置的指针),成功时将返回指向旧块(或新位置)的指针,失败时将返回NULL。如果无法分配新块,则不会更改旧块。

-4

编辑:更正,一些人因我所说的话而抨击我,你分配指针的方式似乎是最佳实践之一,我被教导始终遵循使用类型转换在sizeof()中,但显然你的方法更正确,所以请忽略我所说的 =)

先看看http://en.wikipedia.org/wiki/Malloc#realloc可能对你有好处。

你可能不太理解 sizeof() - 它返回以字节为单位传递给它的参数的大小。例如,在大多数32位系统上,sizeof(int) 的值为4,但你仍然应该使用 sizeof(int) 而不是 4,因为在64位系统上编译代码(只是举个例子)将使该值等于8,而你的代码仍然可以正常编译。你要分配内存用于什么?指针吗?如果是这样,你应该使用 sizeof(void*)(你可以说 sizeof(int*),但通常约定不提及编译器想要在这些指针中存储什么,因为所有指针应该具有相同的大小 - 所以大多数程序员说 sizeof(void*)),如果你需要字符空间,则使用 sizeof(char) 等。

但是,你确实正确地将 realloc() 的返回值存储在一个新指针中并进行检查,尽管很多程序员会假设系统总是有足够的内存并且可以轻松应对。


他对 sizeof 的使用是完全正确的。sizeof(*ptr) 是由 ptr 指向的对象的大小,因此 ptr = malloc(sizeof(*ptr) * N); 是正确和惯用的(尽管个人认为我会将其写成 ptr = malloc(N * sizeof ptr[0]);,但那只是风格问题)。 - caf
相反,OP在他的代码中的做法正是应该采取的方式。内存分配请求应尽可能地与类型无关:在内存分配函数的结果上不需要强制转换,在sizeof下也不需要类型名称。在malloc请求(等等)中使用类型名称的奇怪习惯早已被淘汰了。类型名称属于声明。如果不是声明,则不允许使用类型名称(尽可能)。 - AnT stands with Russia
foo = malloc(count * sizeof *foo); 是一种确保获得正确大小的标准习语。你对问题的作者像他对 C 一无所知,而自己却忽略了一些非常基本的东西。 - R.. GitHub STOP HELPING ICE

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