2

下面是代码:

#include <stdio.h>
#include <stdlib.h>
int main()
{
    int *p;
    p=(int *)malloc(sizeof(int));
    *p=5;
    printf("Before freeing=%p\n",p);
    printf("Value of p=%d\n",*p);
    //making it dangling pointer
    free(p);
    printf("After freeing =%p\n",p);
    printf("Value of p=%d\n",*p);
    return 0;
}

下面是输出:

Before freeing=0x1485010
Value of p=5
After freeing =0x1485010
Value of p=0

释放指针后,解除引用给出输出“0”(零)。

下面是另一个也给出“0”的代码

include <stdio.h>
#include <stdlib.h>
int main()
{
int *p;
p=(int *)malloc(sizeof(int));

printf("Before freeing=%p\n",(void *)p);
printf("Value of p=%d\n",*p);
return 0;
}

在这个我没有释放内存,只是分配它,它仍然给出'0'。是不是每个未初始化指针的默认值都是'0'?

为什么会这样?

4

4 回答 4

5

不要依赖这个,这是未定义的行为。free()不必将指针设置为零,这正是您当前的实现正在为您做的事情。如果您想 100% 确定,无论您的编译器、平台等如何,NULL在释放它之后将指针设置为。

于 2013-10-22T16:20:50.023 回答
3

如果我们查看涵盖未定义行为的 C99 草案标准,这只是未定义行为Annex J.2

在以下情况下,行为未定义:

并包括以下项目符号:

使用指向由调用 free 或 realloc 函数释放的空间的指针的值 (7.20.3)。

在free'ing 之后设置一个指针NULL通常是一个好主意,您可以在这里找到关于该主题的很好的讨论。

于 2013-10-22T16:20:54.253 回答
1

取消引用无效指针会导致每个规范未定义的结果。不保证会失败。

于 2013-10-22T16:22:22.150 回答
1

虽然“没关系,它是 UB”的答案通常就足够了,但人们可能会好奇为什么值会发生变化。好奇心是(恕我直言)了解某事发生原因的正当理由。

这取决于内存管理,它可能决定存储“下一个空闲块”的地址或释放的内存区域中的任何内容。

所以你观察到的可能是内存管理的一个动作。

例如,内存管理可能以管理两个链表和一个上指针的方式实现。一个链表包含分配的内存块,可能指向“真正可用”内存之前的 8 或 16 个字节,另一个链表指向第一个空闲块,该块又包含指向下一个空闲块的指针。上指针上方的内存被认为是空闲的。

如果释放第一个内存块,则空闲列表指针指向它,并且它的第一个指针大小的数据为零,这意味着没有其他释放的块。这就是您将内存清零的原因。

很高兴知道这些东西的存在以及它们是如何工作的,但要避免在生产程序中使用这些知识。有一天,它们可能会落在你的脚上……

于 2013-10-22T16:23:18.640 回答