【问题标题】:dangling pointer, reason for value change after free()?悬空指针,free() 后值更改的原因?
【发布时间】:2011-02-03 06:20:53
【问题描述】:

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

据我了解,x指向的堆中的内存,y仍然指向的内存,还没有分配给别人,怎么改成0 ?

而且,我不认为是 free(x) 将其更改为 0。

有没有cmets?

#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;
}

【问题讨论】:

  • 太阳耀斑。这几乎总是因为太阳耀斑。

标签: c pointers dangling-pointer


【解决方案1】:

free() 的调用会将malloc() 分配的内存块放回C 运行时为堆维护的数据结构中(在这种情况下,可能称为“空闲列表”)。

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

在程序的非调试版本中,运行时通常不会专门做任何事情来使释放的内存无效,但正如我所提到的,它仍可能由于自己的簿记而进行更改(尽管由于内存没有'不再属于调用者,运行时可以为所欲为)。

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

【讨论】:

    【解决方案2】:

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

    y = x;

    如果你释放x,你也将释放y指向的内存。

    如果您想知道为什么它会打印“0”,即未定义的行为,但我之前将其视为一种做法,即一些程序员将释放区域设置为“0”。

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

    【讨论】:

    • 我了解什么是悬空指针!,我只是想了解 y=0 的行为。
    【解决方案3】:

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

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

    【讨论】:

    • +1,绝对。这个问题实际上是没有意义的,因为没有明确的答案。
    • 除了通常调试堆管理器会显式地用 零以外的东西填充释放的内存。
    • @Cruachan - 不是毫无意义,答案很明确,它未定义。未定义就是未定义。
    【解决方案4】:

    free 中所做的事情取决于实现。内存释放后不禁止清零。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-11-06
      • 1970-01-01
      • 1970-01-01
      • 2018-10-11
      • 2016-07-03
      • 1970-01-01
      • 2011-10-28
      • 1970-01-01
      相关资源
      最近更新 更多