如果我重新分配并且新大小为 0,会发生啥情况。这是不是等同于免费?

Posted

技术标签:

【中文标题】如果我重新分配并且新大小为 0,会发生啥情况。这是不是等同于免费?【英文标题】:What happens if I re-alloc and the new size is 0. Is this equivalent with a free?如果我重新分配并且新大小为 0,会发生什么情况。这是否等同于免费? 【发布时间】:2011-02-02 13:05:25 【问题描述】:

给定以下代码:

int *a = NULL;
a = calloc(1, sizeof(*a));
printf("%d\n", a);
a = realloc(a, 0);

printf("%d\n", a);
return (0);

返回:

4078904
0

这个 realloc 等同于 free 吗?

注意: 我在 WindowsXP 下使用 MinGW。

【问题讨论】:

【参考方案1】:

它可能等同于也可能不等同于在指针上调用free;结果是实现定义的。

来自 C99 标准(§7.20.3/1):

如果请求的空间大小为零,则行为是实现定义的:要么返回空指针,要么行为就好像大小是某个非零值,但返回的指针不应用于访问一个对象。

这适用于所有内存管理功能,包括realloc

【讨论】:

相当于调用free,原来的内存已经不能使用了。另请参阅我的回答 - 它引用了 §7.20.3.4 (realloc) 中的信息以及您引用的部分。 §7.20.3.4 中的材料覆盖了一般注释 - 或者,更确切地说,指定 realloc() 释放 - 释放 - 原始内存,然后对新大小执行相当于 malloc() 的操作,相当于 malloc(0)在这种情况下,然后获取您引用的行为。 key的区别是realloc()无条件先释放旧内存。 @Jonathan:如果行为是“好像大小是某个非零值”,那么未能释放结果指针将导致内存泄漏。在这种情况下,它并不严格等同于在指针上调用 free。【参考方案2】:

不一定。

它通常与 link that munissor posted 一样,但 Mac OS 10.5 手册页说:

如果 size 为零且 ptr 不为 NULL,则分配一个新的、最小大小的对象并释放原始对象。

什么是“最小尺寸对象”?好吧,任何分配器都会存储一些关于分配的信息,这会占用通常分配给用户的空间之外的空间。据推测,“最小尺寸对象”只是这些标头之一加上为用户保留的零字节空间。

我猜想这个条款的存在是为了支持标准化时存在的实现,并且这些实现对于调试分配行为很有用。


致地址Jonathan's comments

考虑两者的区别

for (int i=0; i<VERY_BIG_NUMBER; ++i)
  char *p = malloc(sizeof(char[10]));
  free(p);

for (int i=0; i<VERY_BIG_NUMBER; ++i)
  char *p = malloc(sizeof(char[10]));
  realloc(p,0);

通过mallocfree 的合理实现,第一个剪辑不会无限制地消耗内存。但如果 realloc 实现返回那些“最小尺寸的对象”,它可能会。

当然,这个例子是人为的,它依赖于理解“最小尺寸对象”的含义,但我认为文本允许这样做。

简而言之,如果你意思是 free,你应该说free

【讨论】:

我认为这些实现不遵循 C 规范。也看看opengroup.org/onlinepubs/009695399/functions/realloc.html @munissor:此行为符合要求。来自 POSIX 规范:“如果大小为 0,则应返回空指针或 可以成功传递给 free() 的唯一指针”(强调我的)。它也符合 C 标准中的语言。 @munissor:我手边没有 K&R,因此无法与 '89 标准进行比较,但 Mac OS 使用已经存在很长时间的 BSD 实现。当然,James McNellis 发布的链接表明这种行为 在 '99 标准下是允许的。无论如何,结果几乎相同。 (我怀疑“最小尺寸的对象”是为了支持一些 malloc 调试器。) @james, @dmkee 很高兴知道!永远不要相信您可以在 Google 上找到的内容;)【参考方案3】:

http://www.cplusplus.com/reference/clibrary/cstdlib/realloc/ 说是的。

【讨论】:

这似乎与 C 标准相矛盾。【参考方案4】:

是的

C99 标准 §7.20.3.4 (realloc) 说:

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

如果 ptr 是空指针,则 realloc 函数的行为类似于 malloc 函数 规定的大小。否则,如果 ptr 与先前返回的指针不匹配 calloc、malloc 或 realloc 函数,或者如果空间已被调用释放 对于 free 或 realloc 函数,行为是未定义的。如果记忆为新 对象不能被分配,旧对象没有被释放,它的值不变。

这清楚地表明旧对象已被释放(释放)。返回值可能是空指针,也可能是第 7.20.3 节的一般说明中指定的值:

如果请求的空间大小为零,则行为由实现定义: 返回一个空指针,或者行为就像大小是一些 非零值,但返回的指针不得用于访问对象。

无论哪种方式,您都不能取消引用返回的值:它可以用作free() 的参数,或者传递给其他函数,只要它们反过来不引用它。

【讨论】:

很明显,现有数据不再可访问。但尚不清楚原始调用分配的所有内存是否都已返回:分配器可能正在为产生的零大小分配维护一个唯一且不可回收的记录。

以上是关于如果我重新分配并且新大小为 0,会发生啥情况。这是不是等同于免费?的主要内容,如果未能解决你的问题,请参考以下文章

如果我在使用新程序和结束程序分配数据后没有调用删除运算符会发生啥?

如果 ThreadPool 线程死亡会发生啥?

如果我为无符号变量分配负值会发生啥?

当向量需要更多内存并重新分配内存时,指针会发生啥?

如果自动扩缩功能无法创建新实例,App Engine 请求会发生啥情况?

我是不是应该强制重新分配检查新块大小是不是小于初始块?