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
失败。我在5
free()
ingptr
5
上做正确的事吗?
【问题讨论】:
你那里的东西看起来不错,只要你检查过原来的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 names 在sizeof
下。在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..:不,不是。你只是误解了重点。确实,在 C99realloc
中,大小为 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 时的正确用法是啥?的主要内容,如果未能解决你的问题,请参考以下文章