realloc() 失败并返回 NULL 时的正确用法是啥?

Posted

技术标签:

【中文标题】realloc() 失败并返回 NULL 时的正确用法是啥?【英文标题】:What is the correct usage of realloc() when it fails and returns NULL?realloc() 失败并返回 NULL 时的正确用法是什么? 【发布时间】:2011-03-20 20:40:35 【问题描述】:

谁能总结一下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.  

假设realloc() 在线3 失败。我在5free()ingptr5 上做正确的事吗?

【问题讨论】:

你那里的东西看起来不错,只要你检查过原来的malloc是成功的。 实际上,即使原始的 malloc() 失败,realloc() 的第一个参数也可以使用空指针 - 然后它的行为类似于 malloc(),并且(在这种情况下)可能会失败也是(因为如果malloc() 不能分配 50 个字节,realloc() 可能也不能分配 60 个字节)。 【参考方案1】:

编辑:更正,有些人因为我所说的而抨击我,你分配指针的方式似乎是其中的最佳实践,我被教导总是在 sizeof() 中使用类型转换,但显然你的方式更正确,所以无视我说的=)

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

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

然而,您可以将realloc() 的返回值存储在一个新指针中并检查它,尽管许多程序员会假设系统总是有足够的内存并侥幸成功。

【讨论】:

他对sizeof 的使用完全正确。 sizeof(*ptr)ptr 所指向的东西的大小,所以ptr = malloc(sizeof(*ptr) * N); 是正确且惯用的(虽然我个人会写成ptr = malloc(N * sizeof ptr[0]);,但这只是风格) 恰恰相反:OP 在他的代码中执行的方式正是它应该执行的方式。内存分配请求应尽可能与类型无关:no cast 对内存分配函数的结果和no type namessizeof 下。在malloc 请求(等等)中使用sizeof 下的类型名称的奇怪习惯早已在C 编程的垃圾箱中占据了一席之地。类型名称属于声明。如果不是声明,则不允许使用类型名称(尽可能)。 foo = malloc(count * sizeof *foo); 是确保您获得正确尺寸的标准习语。你对待问题的作者就像他对 C 一无所知,而自己却错过了一些非常基本的东西..【参考方案2】:

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

还要记住,在 C89/90 中,如果您发出目标大小为零的 realloc 请求,即使原始内存已成功释放,realloc 函数也可能返回空指针。这是 C89/90 中的一个缺陷,因为在返回 null 时无法区分成功与失败。

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

【讨论】:

据我所知这是错误的。当目标大小为0时,C99不保证非空返回;它允许任何一种行为。除了一些 GNU ***者之外,大多数人似乎认为 return 0 行为是更好的选择。而且如果target size为0,realloc不会失败,也就不需要检查失败了。 @R..:不,不是。你只是误解了重点。确实,在 C99 realloc 中,大小为 0 可以返回 null 或非 null,但是在 C99 中,“null 表示失败”和“non-null 表示成功”的关系是严格的。 IE。如果realloc 在 C99 中返回 null,则保证原始内存被释放。在 C89/90 中,这种关系并不严格:如果您以 0 大小调用 realloc 并得到 null 结果,您无法确定内存是否被释放。 @R..:您最后关于“realloc 不能失败”的评论是不正确的。语言规范不保证(也从未保证)大小为零的realloc 不会失败。可以的。 好的,我正在阅读 POSIX 版本的文档,其中添加了一句:“如果 size 为 0 且 ptr 不是空指针,则指向的对象被释放。”与政策相反,POSIX 未能将这句话标记为“CX”。在其他来源中的进一步阅读表明,C89 具有正确的要求,即目标大小为 0 的 realloc 充当免费的,而 C99 打破了它。无论如何,任何真正有价值的实现都将遵循 POSIX,至少...... 我找不到您声称存在的此类要求。你能提供引用吗?【参考方案3】:

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

【讨论】:

【参考方案4】:

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

如果 realloc 根本找不到足够的空间,它会返回一个空指针,并保留之前分配的区域。

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

【讨论】:

以上是关于realloc() 失败并返回 NULL 时的正确用法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

如果失败,realloc 会释放前一个缓冲区吗?

malloc realloc calloc的区别

realloc:没有足够的空间

realloc 错误:释放对象的校验和不正确

在不移动数据的情况下在 CUDA 中实现 realloc

单击时的DataTable锚事件不起作用,并返回加载资源失败