【问题标题】:The state of a pointer after deallocation释放后指针的状态
【发布时间】:2018-05-06 23:44:30
【问题描述】:

调用free()函数后,动态分配内存的指针指向什么。 指针是否指向 NULL,或者它仍然指向它在释放之前指向的相同位置。 free() 的实现是否对此有某种标准,或者它在不同平台上的实现方式不同。

uint8_t * pointer = malloc(12);
printf("%p", pointer); // The current address the pointer points to
free (pointer);
printf("%p", pointer); // must it be NULL or the same value as before ?

编辑: 我知道 printf 会产生相同的结果,我只是想知道我是否可以依靠不同的实现。

【问题讨论】:

  • 为什么要在 free() 之后 printf?为什么要指望它?
  • @VinayakGarg:我认为这更像是一个调试打印语句。
  • @VinayakGarg 我正在编写嵌入式设备,并在某项任务中分配内存。一旦我得到一个更高优先级并且还需要分配内存的中断,就会出现问题。我需要在不知道分配成功与否的情况下释放之前分配的内存。

标签: c memory-management


【解决方案1】:

指针值没有被修改。您将指针(内存地址)按值传递给free()free() 函数无权访问pointer 变量,因此无法将其设置为NULL

两个printf() 调用应该产生相同的输出。

【讨论】:

  • 投反对票的巨魔能否解释他们投票的原因?谢谢。
  • 我猜要么有人真的喜欢我的回答,要么我马上就要投反对票了...
  • 是的,规范纳粹倾向于对技术性的答案投反对票,这使得它们在理论上不正确,但在实践中几乎无处不在。 :S 无论如何,我想我们都同意,在你释放后使用指针值是一件非常糟糕的事情,无论你使用的是哪个 C 实现。
  • 不是downvoter,但读取释放的指针可能理论上会在某些硬件(使用专用地址寄存器)上导致无效地址陷阱。
  • @BoPersson 这样的环境将如何处理代码void * foo = malloc(10); void * bar = foo; free(foo);——bar 是否也设置为陷阱值?
【解决方案2】:

根据标准(C99 6.2.4/2):

当指针指向的对象时,指针的值变得不确定 达到其生命周期的终点。

实际上,我所知道的所有实现都会为您的示例代码打印两次相同的值。但是,允许当你释放内存时,指针值本身变成了一个陷阱表示,当你尝试使用指针的值时,实现会做一些奇怪的事情(即使你没有' t 取消引用它)。

假设一个实现想要做一些不寻常的事情,我认为硬件异常或程序中止将是最合理的。但是,您可能不得不想象一个实现/硬件会做很多额外的工作,因此每次将指针值加载到寄存器中时,它都会以某种方式检查地址是否有效。这可能是通过在内存映射中检查它(在这种情况下,我想我的假设实现只会在包含分配的整个页面已被释放和未映射时捕获),或其他方式。

【讨论】:

    【解决方案3】:

    free() 只释放内存。指针仍指向旧位置(悬空指针),您应手动将其设置为NULL

    将指针设置为NULL 是一个好习惯。由于内存位置可能会被其他对象重用,您可能能够访问和修改不属于您的数据。这特别难以调试,因为它不会产生崩溃,或者在某些不相关的点产生崩溃。如果您访问不存在的对象,设置为 NULL 将保证可重现的崩溃。

    【讨论】:

    • 将代码更改为 { uint8_t * pointer = malloc(12); ... free(pointer); } 比将其设置为 null 要好得多。如果您确保指针在悬空时立即超出范围,则不能使用悬空指针。
    【解决方案4】:

    我在 C++ 中尝试过这段代码

    #include<iostream>
    using namespace std;
    int main(void)
    {
        int *a=new int;
        *a=5;
        cout<<*a<<" "<<a<<"\n";
        delete a;
        *a=45;
        cout<<*a<<" "<<a<<"\n";
    }
    

    输出是这样的

    5 0x1066c20
    45 0x1066c20
    

    再次运行产生了类似的结果

    5 0x13e3c20
    45 0x13e3c20
    

    因此,在 gcc 中,指针似乎在释放后仍指向相同的内存位置。 此外,我们可以修改该位置的值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-30
      相关资源
      最近更新 更多