悬空指针,free()后价值变化的原因?

时间:2010-04-01 07:19:24

标签: c pointers dangling-pointer

在以下代码段中,在free(x)之后,为什么y变为0?

根据我的理解,x指向的堆中的内存仍然被y指向,但是还没有分配给其他人,所以如何才能它改为0?

此外,我不认为free(x)将其更改为0。

有任何意见吗?

#include <stdio.h>

int main(int argc, char *argv[])
{
    int *y = NULL;
    int *x = NULL;

    x = malloc(4);
    *x = 5;

    y = x;
    printf("[%d]\n", *y); //prints 5

    free(x);

    printf("[%d]\n", *y); //why doesn't print 5?, prints 0 instead

    return 0;
}

4 个答案:

答案 0 :(得分:12)

这是未定义的行为,解释只是推测。

我可以推测,你可能正在运行C库的调试版本,并且free()的调试版本确实将指向区域归零。

答案 1 :(得分:4)

free所做的工作取决于实施。在释放内存后,不禁止将内存清零。

你正在做的是未定义的行为。

答案 2 :(得分:2)

y 指向与 x 相同的地址,行

y = x;

如果您释放 x ,您还可以释放 y 指向的内存。

如果你想知道为什么它打印'0',那个未定义的行为,但我之前已经看过它,一些程序员,将释放区域设置为'0'。

下载此视频名为"Binky the pointer fun video"(这不是一个玩笑,实际上非常有教育意义),你会得到更好的指示。

答案 3 :(得分:2)

free()的调用会将已由malloc()分配的内存块放回到C运行时为堆维护的数据结构中(在这种情况下可能被称为'free的内容) -list)。

操作堆数据结构可能会偶然改变y指向的内容(因为程序不再拥有内存,所以没有理由相信内存不应该更改)。

在程序的非调试版本中,运行时通常不会做任何特别的事情来使释放的内存无效,但正如我所提到的,它可能仍然会因为自己的簿记而进行更改(尽管因为内存不存在)不再属于调用者,允许运行时做任何它喜欢的事情。

在调试版本中,运行时可能会显式地将内存覆盖为一个值,如果程序确实使用该值,则希望它会导致更容易识别问题的问题。通常,用于覆盖释放的内存块的值不为零,因为零通常不会暴露错误(即NULL指针检查将导致代码“处理”无效的内存访问)。例如,MSVC的调试堆管理器将使用值0xDD覆盖释放的内存(有关详细信息,请参阅When and why will an OS initialise memory to 0xCD, 0xDD, etc. on malloc/free/new/delete?)。