5

我正在为考试而学习,我想知道这些是否等同于 free(ptr):

 malloc(NULL); 

 calloc(ptr); 

 realloc(NULL, ptr); 

 calloc(ptr, 0); 

 realloc(ptr, 0);

据我了解,这些都不起作用,因为 free() 函数实际上告诉 C ptr 之后的内存再次可供它使用。抱歉,这是一个菜鸟问题,但我们将不胜感激。

4

3 回答 3

14

实际上,最后一个相当于调用free(). 仔细阅读规范realloc(),你会发现它可以重新分配数据,或者改变分配的大小(特别是如果新的大小比旧的大,可能会移动数据),它可以释放内存也。实际上,您不需要其他功能;它们都可以用realloc(). 并不是说任何头脑正常的人都会这样做……但这是可以做到的。

有关函数族危险的完整剖析,请参阅 Steve Maguire 的“ Writing Solid Code ”。malloc()有关阅读“编写可靠代码”的风险的完整剖析,请参见ACCU网站。我不相信它会像评论所说的那么糟糕——尽管它完全缺乏对它的处理const确实过时了(回到 90 年代初,当时 C89 还是新的并且没有被广泛实施)。


D McKee 关于 MacOS X 10.5 (BSD) 的笔记很有趣……

C99 标准说:

7.20.3.3 malloc 函数

概要

#include <stdlib.h>
void *malloc(size_t size);

描述

malloc 函数为大小由 size 指定且值不确定的对象分配空间。

退货

malloc 函数返回空指针或指向已分配空间的指针。

7.20.3.4 realloc 函数

概要

#include <stdlib.h>
void *realloc(void *ptr, size_t size);

描述

realloc 函数释放 ptr 指向的旧对象,并返回一个指向具有 size 指定大小的新对象的指针。新对象的内容应与释放前旧对象的内容相同,直至新旧大小中的较小者。新对象中超出旧对象大小的任何字节都具有不确定的值。

如果 ptr 是空指针,则 realloc 函数的行为类似于指定大小的 malloc 函数。否则,如果 ptr 与 calloc、malloc 或 realloc 函数先前返回的指针不匹配,或者如果空间已通过调用 free 或 realloc 函数被释放,则行为未定义。如果无法为新对象分配内存,则不会释放旧对象并且其值不变。

退货

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 的基本原理……它说:

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 函数

一个空的第一个参数是允许的。如果第一个参数不为null,而第二个参数为0,则调用释放第一个参数指向的内存,并且可能返回一个null参数;C99 与不允许零大小对象的策略一致。

C99的一个新特性:realloc函数被改变,明确指向的对象被释放,一个新的对象被分配,新对象的内容与旧对象的内容相同,直到更小两种尺寸。C89 试图指定新对象是与旧对象相同的对象,但可能具有不同的地址。这与标准中假定对象的地址在其生命周期内保持不变的其他部分相冲突。此外,在大小为零时支持实际分配的实现不一定会在这种情况下返回空指针。C89 似乎需要一个空返回值,委员会认为这太严格了。


Thomas Padron-McCarthy 观察到

C89 明确表示:“如果 size 为零且 ptr 不是空指针,则释放它指向的对象。” 所以他们似乎已经删除了C99中的那句话?

是的,他们删除了那句话,因为它被开头的句子所包含:

realloc 函数释放 ptr 指向的旧对象

那里没有回旋的余地;旧对象被释放。如果请求的大小为零,那么您将返回malloc(0)可能返回的任何内容,这通常(通常)是一个空指针,但也可能是一个非空指针,也可以返回,free()但不能合法地取消引用。

于 2009-04-15T02:25:09.243 回答
4
realloc(ptr, 0);

相当于free(ptr);(尽管我不建议这样使用它!)

另外:这两个调用彼此等价(但不是免费的):

realloc(NULL,size)
malloc(size)
于 2009-04-15T02:21:22.277 回答
0

最后一个realloc(ptr, 0)——接近了。它将释放任何已分配的块并用最小的分配替换它(我的 Mac OS X 10.5 联机帮助页说)。检查您的本地手册页以查看它在您的系统上的作用。

也就是说,如果ptr指向一个实体对象,您将取回它的大部分内存。


Debian Lenny 的手册页同意MitchJonathan ... BSD 真的在这方面与 Linux 不同吗?


从有问题的手册页:

realloc() 函数尝试将 ptr 指向的分配大小更改为 size,并返回 ptr。[...] 如果 size 为零且 ptr 不为 NULL,则分配一个新的、最小大小的对象并释放原始对象。


linux 和 solaris 手册页非常干净,'89 标准:realloc(ptr,0)free(ptr). 上面的 Mac OS 手册页和 Jonathan 引用的标准不太清楚,但似乎留下了打破等价的空间。

我一直想知道为什么会有差异:“像自由一样”的解释对我来说似乎很自然。我可以访问的两个实现都包含一些环境变量驱动的可调性,但 BSD 版本接受更多选项一些示例:

 MallocGuardEdges             If set, add a guard page before and after
                              each large block.  
 MallocDoNotProtectPrelude    If set, do not add a guard page before large
                              blocks, even if the MallocGuardEdges envi-
                              ronment variable is set.

 MallocDoNotProtectPostlude   If set, do not add a guard page after large
                              blocks, even if the MallocGuardEdges envi-
                              ronment variable is set.

 MallocPreScribble            If set, fill memory that has been allocated
                              with 0xaa bytes.  This increases the likeli-
                              hood that a program making assumptions about
                              the contents of freshly allocated memory
                              will fail.
 MallocScribble               If set, fill memory that has been deallo-
                              cated with 0x55 bytes.  This increases the
                              likelihood that a program will fail due to
                              accessing memory that is no longer allo-
                              cated.

free在正常模式下,“最小尺寸的对象”可能什么都不是(即等同于),而是有一些保护措施到位的东西。把它当作它的价值。

于 2009-04-15T02:22:25.333 回答