free()是否删除存储在动态分配的内存中的数据?

时间:2014-10-03 17:07:10

标签: c linux

我写了一个简单的程序来测试free()之后动态分配的内存的内容,如下所示。 (我知道我们不应该在免费后访问内存。我写了这个来检查免费后内存中会有什么内容)

#include <stdio.h>
#include <stdlib.h>

main()
{
    int *p = (int *)malloc(sizeof(int));

    *p = 3;
    printf("%d\n", *p);
    free(p);

    printf("%d\n", *p);
}

输出:     3     0

我认为它会打印垃圾值或第二次打印声明崩溃。但它总是打印0。

1)此行为是否依赖于编译器?

2)如果我尝试使用free()两次释放内存,则会生成核心转储。在手册页中,提到程序行为异常。但我总是得到核心转储。这种行为是否还取决于编译器?

4 个答案:

答案 0 :(得分:3)

  

free()是否删除动态分配的内存中存储的数据?

没有。 free只释放其参数(指针)指向的已分配空间。此函数接受指向先前分配的内存块的char指针,并释放它 - 也就是说,将其添加到可重新分配的可用内存块列表中。 释放的存储器不会以任何方式清除/擦除。

你不应该取消引用释放(悬空)指针。标准说:

7.22.3.3自由功能:

  

[...]否则,如果参数与先前由内存管理返回的指针不匹配   函数,或者如果通过调用freerealloc释放了空格,则行为未定义

上面的引用还指出,释放指针两次将调用未定义的行为。一旦UB运行,您可能会得到预期的意外结果。可能存在程序崩溃或核心转储。

答案 1 :(得分:3)

如gnu网站所述

释放块会改变块的内容。在释放它之后,不要期望在块中找到任何数据(例如指向块链中下一个块的指针)。

因此,释放后访问内存位置会导致未定义的行为,尽管free不会更改内存位置中的数据。在这个例子中,你可能会得到0,你可能会在其他一些例子中得到垃圾。

并且,如果你试图释放内存两次,在第二次尝试时你会试图释放一个未分配的内存,这就是为什么你要进入核心转储。

答案 2 :(得分:0)

就标准C而言,它没有被指定,因为它是不可观察的。只要你free内存,指向那里的所有指针都是无效的,所以无法检查那个内存。 *)

即使你碰巧有一些标准的C库记录某种行为,你的编译器仍然可能会认为指针在传递给free后没有被重用,所以你仍然不能指望任何特定的行为。

*)我认为,即使阅读这些指针也是UB,不仅是解除引用,而且无论如何这都无关紧要。

答案 3 :(得分:0)

除了以上关于use-after-free语义的所有解释之外,你真的可能想要调查每个C程序员的生命保护程序:valgrind。它会自动检测代码中的此类错误,并且通常会将您的隐藏在现实世界中。 Coverity和所有其他静态代码检查器也很棒,但valgrind很棒。