c-Do free()删除存储在动态分配的内存中的数据



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

#include <stdio.h>
#include <stdlib.h>
main()
{
    int *p = (int *)malloc(sizeof(int));
    *p = 3;
    printf("%dn", *p);
    free(p);
    printf("%dn", *p);
}

输出:3.0

我以为它会打印垃圾值,或者在第二次打印语句时崩溃。但它总是打印0。

1) 这种行为取决于编译器吗?

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

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

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

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

7.22.3.3自由功能:

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

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

如gnu网站中所述

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

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

而且,如果你两次尝试释放内存,第二次尝试时,你会试图释放未分配的内存,这就是你进入核心转储的原因。

除了以上所有关于在自由语义之后使用的解释之外,您可能真的想研究每个C程序员的救命稻草:valgrind。它会自动检测代码中的此类错误,并在现实世界中保存您的信息。Coverity和所有其他静态代码检查器也很棒,但valgrind很棒。

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

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

*)我认为,即使读取这些指针也是UB,不仅取消引用,而且这在这里也无关紧要。

最新更新