释放已分配内存:realloc() vs. free()

16

我使用malloc()分配了一块内存,然后用realloc()修改了它。

在代码的某个点上,我想要清空它,也就是说,将其内存大小设置为0。直觉上,这可以通过realloc(pointer, 0)来完成。但我在这里阅读到,这是由具体实现决定的,不应该使用。

那么我应该使用free()来释放内存,然后再使用malloc()重新分配内存吗?


9
“empty it”是什么意思? - Oliver Charlesworth
7个回答

17

这要看你的意思: 如果你想“清空已使用的内存”,但仍然需要访问该内存,则可以使用 memset(pointer, 0, mem_size);,将该内存重新初始化为零。
如果不再需要该内存,则只需调用free(pointer);,这将释放内存,以便别处可以使用。

在某些系统上使用realloc(pointer, 0)可能像free一样工作,但这并不是标准行为。C99或C11标准未指定realloc(ptr, 0)等效于free(ptr)

realloc(pointer, 0)不等同于free(pointer)

标准(C99,§7.22.3.5):

realloc函数
概述
1#include <stdlib.h>
void *realloc(void *ptr, size_t size);
描述 2 realloc函数释放ptr指向的旧对象,并返回一个指针,该指针指向大小由size指定的新对象。新对象的内容应与先前解除分配之前的旧对象相同,最多到新旧大小中较小的那个为止。新对象中超出旧对象大小的任何字节都具有不确定的值。 3 如果ptr是空指针,则realloc函数根据指定的大小像malloc函数一样工作。否则,如果ptr与先前由内存管理函数返回的指针不匹配,或者该空间已被调用free或realloc函数释放,则其行为未定义。如果无法为新对象分配内存,则不会解除分配旧对象,并且其值保持不变。 返回 4 realloc函数返回一个指向新对象的指针(可能具有与旧对象相同的值),如果无法分配新对象,则返回空指针。

正如您所看到的,它没有为realloc调用指定大小为0的特殊情况。相反,它只说明在分配内存失败时返回NULL指针,在所有其他情况下返回指针。然后,一个指向0字节的指针将是一个可行的选项。

引用相关问题:

更直观地说,realloc在概念上等同于在另一个指针上malloc + memcpy + free,而mallocing一个0字节的内存块会返回NULL或唯一指针,不用于存储任何东西(你要求0字节),但仍需要free。因此,不要像这样使用realloc,它可能在一些实现(即Linux)上工作,但不能保证。

正如链接问题中的另一个答案所述,《C11标准》明确定义了realloc(ptr, 0)的行为为实现定义

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


谢谢,这正是我想要的。我希望能够在以后再次重新分配内存。 - user3021085
@user3021085:你应该尽可能释放内存,同时确保使用realloc(pointer, 1)仍然可以保留指针,这将释放接近所有的内存,而且你仍然可以使用指针。 - Elias Van Ootegem
是的,但我有一些信息要检查。如果我分配给1,可能会出现未定义的行为。 - user3021085
@user3021085:那就简单地使用realloc(pointer, sizeof *pointer)... 我不明白这怎么会导致未定义的行为... - Elias Van Ootegem
这在C89/C90标准中是必须的。当时使用realloc(pointer,0)释放它是强制性的。我认为在较新的C和POSIX标准中不释放它是强制性的。 - 12431234123412341234123

5

realloc()被用来增加或减少内存,而不是释放内存。

点击这里,并使用free()来释放内存(链接)。


4
我认为你的意思不是“空”,那意味着“将其设置为空值,我认为它是空的”(通常所有位都为零)。你的意思是释放或取消分配。

手册页面说:

如果ptr为NULL,则对于所有的size值,调用等效于malloc(size);如果size等于零且ptr不是NULL,则调用等效于free(ptr)

传统上,您可以使用realloc(ptr, 0);作为free(ptr);的同义词,就像您可以使用realloc(NULL, size);作为malloc(size);的同义词一样。不过我不建议这样做,因为有点令人困惑,不符合人们的预期使用方式。

然而,现代C语言中定义已经改变:现在realloc(ptr, 0);将释放旧内存,但接下来会做什么并没有明确定义:这是实现相关的。

所以:不要这样做:使用free()释放内存,并让realloc()仅用于将大小更改为非零值。


1
这种使用realloc()的方式似乎已经过时了。请看一下我的答案。 - alk
是的,似乎变得不太明确了。我进行了编辑,谢谢。 - unwind
现在,realloc(ptr, 0)将释放旧内存,但下一步做什么并不明确:这是实现定义的。如果realloc返回NULL,则表示分配失败,在分配失败时,旧内存不会被释放。 - user743382

4
使用free()函数释放动态分配的内存。尽管早期文档说明realloc(p, 0)等同于free(p),但最新的POSIX文档明确指出这不是这样的:

之前的版本明确允许调用realloc (p, 0)来释放p所指向的空间并返回一个空指针。虽然此行为可以被解释为本标准允许的,但C语言委员会表示这种解释是错误的。

而且:

应用程序应该假设如果realloc()返回一个空指针,则p所指向的空间没有被释放。


2

使用free(pointer); pointer = 0代替realloc(pointer, 0)


2
void* realloc (void* ptr, size_t size);

在C90中:
如果大小为零,则释放在ptr处先前分配的内存,就好像调用了free一样,并返回一个空指针。
在C99中:
如果大小为零,则返回值取决于特定库实现:它可以是空指针,也可以是不应被取消引用的其他位置。

1
我会使用realloc来给指针分配更多或更少的内存,但不会用它来清空指针。要清空指针,我会使用free。

1
"to empty"这个词组在C编程的上下文中并不常见。而且它会产生误导,并不能准确描述释放指针所引用或指向的内存时发生的情况。 - alk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接