我们可以使用 realloc 来释放动态分配的内存吗?

Posted

技术标签:

【中文标题】我们可以使用 realloc 来释放动态分配的内存吗?【英文标题】:Can we free dynamically allocation memory using realloc? 【发布时间】:2017-01-11 09:05:08 【问题描述】:

我和我的朋友就释放动态分配的内存进行了讨论。他告诉我可以用 realloc() 来释放内存,但我拒绝了。 让我们考虑下面的代码:

int main()

    int *p = (int *)malloc(sizeof(int) * 10);
    int *q = (int *)malloc(sizeof(int) * 10);

    free(p);
    p = NULL;

    realloc(q, sizeof(int) * 0);
    q = NULL;

    _getch();
    return 0;

假设 pq 分别指向地址 0x10000x2000。 在上面的代码中,pqint 指针,指向 RAM 中动态分配的 40 字节内存块。在执行 free(p) 时释放内存地址 (0x1000)。释放的内存地址 (0x1000) 可以再次被操作系统使用。然后,将 NULL 分配给指针变量p,以防止p 成为悬空指针。

realloc(q, sizeof(int) * 0);

realloc() 只是将 q 指向的内存块缩小为零。但是 q 仍然指向同一个地址 (0x2000),并且该地址没有被释放。在将 NULL 值分配给指针 q 时,q 现在指向 NULL,并且未释放 q 指向的地址 (0x2000)并且该地址 (0x2000) 的链接丢失。该地址 (0x2000) 在程序结束之前不能被操作系统使用。

我的理解正确吗?

【问题讨论】:

你有什么证据表明q指向的东西没有被释放? 即使realloc()的第二个参数为0,内存分配函数使用的堆中数据结构中的条目也不会被释放(不会返回到可用内存池) ,按设计使用的功能使用它们。 是的,您的理解是正确的,但有一点需要注意。通常当内存分配收缩时,实际保留的内存不会收缩 "realloc() 只是将 q 指向的内存块缩小到零。" --> 也许,也许不是。 C 没有指定realloc() 必须 以这种方式运行。这是一种多种可能性。 【参考方案1】:

realloc(, 0) 是 implementation dependent and not equivalent 到 free()

也就是说,你可能很幸运:

#include <stdio.h>
#include <malloc.h>

int main() 
        char *a;
        a = malloc(1024);
        printf("a = %08lx\n", a);
        free(a);
        a = malloc(1024);
        printf("a = %08lx\n", a);
        realloc(a, 0);
        a = malloc(1024);
        printf("a = %08lx\n", a);


gcc version 6.1.1 20160815 [gcc-6-branch revision 239479] (SUSE Linux)
ldd --version

ldd (GNU libc) 2.23

a = 01dad010
a = 01dad010
a = 01dad010

所以第二个 malloc,在 realloc(, 0) 之后,“看到”了一个空闲块,之前是 a。我认为这意味着在这种情况下realloc 复制了free 的行为。 不要依赖这个

【讨论】:

【参考方案2】:
realloc(q, sizeof(int) * 0);

相同
realloc(q, 0);

7.22.3.5 ->2 中的 C 标准 realloc 函数说:

..并返回一个指向新对象的指针,该对象的大小由 尺寸。新对象的内容应与新对象的内容相同 释放之前的旧对象,直到新旧对象中的较小者 尺寸。

但它没有明确指定如果新大小为零会发生什么。 但是您仍然有一个可以传递给freeartist 指针。

考虑

char *a;
a=malloc(2*sizeof *a);
a=realloc(a,0);
// Note I'm purposely NOT using a temporary variable to store 'realloc' results
// Moreover, above is BAD practice.
free(a); // Is this permitted? YES !! Did we technically free memory above? NO !!
//Compiler will not yell at you for the above, in fact it is legal as per the standard
return 0; // No output for this one

char *a;
a=malloc(2*sizeof *a);
free(a);
//You're not suppose to free(a) again.
free(a); 
//Compiler will yell at you for the above.
return 0;

输出

double free or corruption (fasttop): 0x0000000000915010

结论

deallocationfreeing 并不完全相同。 reallocfree 都可以释放内存,但只有free 可以释放内存。

那是说

free(p);
p = NULL;

是释放内存的推荐方式。请检查[ this ] 答案。

【讨论】:

以上是关于我们可以使用 realloc 来释放动态分配的内存吗?的主要内容,如果未能解决你的问题,请参考以下文章

梦开始的地方—— C语言动态内存管理(malloc+calloc+realloc+free)

堆与栈

找出分配的内存是不是被 C 中的 realloc() 函数释放

为啥在使用 realloc() 进行动态内存分配之后再添加一块内存?

C 存储空间的分配和释放

内存动态分配之realloc(),malloc(),calloc()与new运算符