实际上,最后一个相当于调用free()
。阅读规格realloc()
非常仔细,您会发现它可以重新分配数据,或者更改分配的大小(特别是如果新大小大于旧大小,可能会移动数据),并且它也可以释放内存。事实上,您不需要其他功能;它们都可以写成realloc()
。并不是任何心智正常的人都会这样做……但这是可以做到的。
参见史蒂夫·马奎尔的“编写可靠的代码 https://rads.stackoverflow.com/amzn/click/com/1556155514“为了彻底剖析malloc()
函数族。请参阅ACCU http://accu.org/网站对阅读“编写扎实的代码”的危险进行了完整剖析。我不相信它像评论中所说的那么糟糕 - 尽管它完全缺乏治疗const
它确实有日期(可以追溯到 90 年代初,当时 C89 还很新,尚未广泛全面实施)。
D McKee 关于 MacOS X 10.5 (BSD) 的笔记很有趣......
C99标准说:
7.20.3.3 malloc 函数
Synopsis
#include <stdlib.h>
void *malloc(size_t size);
描述
malloc 函数为大小由 size 和 指定的对象分配空间
其值是不确定的。
Returns
malloc 函数返回空指针或指向已分配空间的指针。
7.20.3.4 realloc 函数
Synopsis
#include <stdlib.h>
void *realloc(void *ptr, size_t size);
描述
realloc 函数释放 ptr 指向的旧对象并返回一个
指向具有 size 指定大小的新对象的指针。新内容
对象应与释放之前的旧对象相同,最多为新旧大小中的较小者。新对象中超出旧对象大小的任何字节都具有不确定的值。
如果 ptr 是空指针,则 realloc 函数的行为类似于 malloc 函数
指定尺寸。否则,如果 ptr 与之前返回的指针不匹配
calloc、malloc 或 realloc 函数,或者空间已通过调用释放
对于 free 或 realloc 函数,行为是未定义的。如果记忆是新的
对象无法分配,旧对象不会被释放,并且它的值不会改变。
Returns
realloc 函数返回一个指向新对象的指针(该对象可能具有相同的属性)
值作为指向旧对象的指针),或者如果新对象无法被调用则为空指针
分配。
除了因额外标头和函数而进行的编辑性更改外,ISO/IEC 9899:2011 标准与 C99 的表述相同,但在第 7.22.3 节中而不是在第 7.20.3 节中。
realloc 的 Solaris 10 (SPARC) 手册页显示:
realloc() 函数将 ptr 的块指针的大小更改为 size 字节,并返回指向(可能移动的)块的指针。内容将保持不变,直至新旧尺寸中较小的一个。如果块的新大小需要块的移动,则释放块的先前实例化的空间。如果新大小更大,则未指定块的新分配部分的内容。如果 ptr 为 NULL,对于指定的大小,realloc() 的行为类似于 malloc()。如果 size 为 0 并且 ptr 不是空指针,则释放指向的空间。
这是一个非常明确的“它像 free() 一样工作”的声明。
然而,MacOS X 10.5 或 BSD 的说法有所不同,这再次证实了我第一段中“没有人头脑正常”的部分。
当然,还有C99 基本原理 http://www.open-std.org/jtc1/sc22/wg14/www/C99RationaleV5.10.pdf...它说:
7.20.3 内存管理函数
这些定义中对空指针和零长度分配请求的处理
功能部分是由支持这种范式的愿望引导的:
OBJ * p; // pointer to a variable list of OBJs
/* initial allocation */
p = (OBJ *) calloc(0, sizeof(OBJ));
/* ... */
/* reallocations until size settles */
while(1) {
p = (OBJ *) realloc((void *)p, c * sizeof(OBJ));
/* change value of c or break out of loop */
}
据报道,这种编码风格不一定得到委员会的认可,但已广泛使用
使用。
某些实现已针对零字节的分配请求返回非空值。
尽管这种策略在理论上具有区分“无”和“零”(未分配的指针与指向零长度空间的指针)的优势,但它具有更引人注目的优势
需要零长度对象概念的理论上的缺点。由于此类物体
无法声明,它们存在的唯一方式就是通过这样的方式
分配请求。
C89 委员会决定不接受零长度对象的想法。分配情况
因此,函数可能会针对零字节的分配请求返回空指针。请注意,这种处理并不排除上面概述的范例。
C89 悄然发生变化
依赖于大小为零的分配请求的程序返回非空指针
会有不同的行为。
[...]
7.20.3.4 realloc 函数
第一个参数为空是允许的。如果第一个参数不为空,并且第二个参数为 0,则调用将释放第一个参数指向的内存,并且空参数可以是
回; C99 与不允许零大小对象的政策是一致的。
C99的一个新特性:realloc 函数已更改,以明确指向的
对象被释放,分配一个新对象,新对象的内容与
旧物体的尺寸,最多为两个尺寸中较小的一个。 C89 尝试指定新对象与旧对象是同一对象,但可能具有不同的地址。这冲突了
标准的其他部分假设对象的地址在其运行期间是恒定的
寿命。此外,当大小为零时支持实际分配的实现不支持
对于这种情况,必须返回一个空指针。 C89 似乎需要 null 返回值,并且
委员会认为这限制太多。
托马斯·帕德隆-麦卡锡 https://stackoverflow.com/users/15727/thomas-padron-mccarthy observed https://stackoverflow.com/questions/750060/is-there-an-alternative-way-to-free-dynamically-allocated-memory-in-c-not-usin/750075?noredirect=1#comment561534_750075:
C89 明确表示:“如果 size 为零且 ptr 不是空指针,则释放它指向的对象。”那么他们似乎在C99中删除了这句话?
是的,他们删除了该句子,因为它包含在开头句子中:
realloc函数释放ptr指向的旧对象
那里没有回旋的余地;旧对象被释放。如果请求的大小为零,那么您将返回任何内容malloc(0)
可能会返回,通常(通常)是一个空指针,但也可能是一个非空指针,也可以返回到free()
但不能合法地取消引用。