释放函数(free())的行为难以理解

3
int main()
{
    int *ptr, **ptr1;
    ptr = (int*)malloc(sizeof(int));
    ptr1 = (int**)malloc(sizeof(int));
    free(ptr);
    *ptr = 12345;
    ptr1 = &ptr;

    //free(ptr);
    //**ptr1 = 23456;
    printf("%d \n", **ptr1);
    system("pause");
    return 0;
}
< p> 当内存已经被释放时,*ptr 如何存储值 12345?所以现在ptr 应该指向 garbage。为什么会发生这种情况?


如果你知道行为是未定义的,为什么还期望特定的行为?显然你期望了某些事情并感到惊讶。 - sellibitze
你应该为每个传递给 free() 的指针设置一个新的目标值。如果没有,请分配 NULL。 - harper
虽然不完全相同,但这个问题的顶部答案基本上已经回答了它:https://dev59.com/ZWw15IYBdhLWcg3wuuCn - jcoder
我也问过类似的问题:http://stackoverflow.com/questions/7007133/how-free-works - Jeegar Patel
5个回答

8

这段代码有很多错误。

  1. 在C语言中,不要将malloc()的返回值进行强制转换。
  2. 你分配的大小是错误的;ptr1 需要 sizeof *ptr1 而不是 sizeof (int)。它是一个指针!
  3. 记得在使用之前检查malloc()的返回值,以防其失败。
  4. 不要在free()之后访问内存。这是未定义行为。

此外,需要注意的是,当你对指针调用free()时,指针本身并没有被销毁;消失的是指针所指向的内存。因此,如果你愿意,仍然可以在指针本身存储一个指针大小的位。虽然很少需要这样做,但在检查这些位时应谨慎。


3
公正地说,这个问题也被标记为C ++。但再次强调,在C ++中不会使用malloc - Luchian Grigore
说“指针所指的内存消失了”是不正确的。实际上,消失的是你使用该内存的许可。这不是一个小问题;它涉及到问题的核心:提问者困惑于在释放内存后仍能够使用内存。告诉他们内存已经消失是错误的,会加深这种困惑:如果内存已经消失,他们怎么能使用它呢?告诉他们内存仍然存在,但不应该使用,即使可以使用,也回答了这个问题。 - Eric Postpischil
令人费解的是,这个答案竟然收到了赞,因为它没有回答问题中的任何一个句子。1-3项与困惑提问者的行为无关。第4项说明了不应该做什么,但并没有解释提问者如何获得他们观察到的结果。有关内存消失的句子是错误的。有关在指针中存储位的句子是无关紧要的,因为所讨论的值12345从未存储在指针中。这个答案中没有任何内容能够解释问题:你可以在已释放的空间中存储,但不应该这样做,因为它可能会被重用。 - Eric Postpischil

4

指针被释放,但它仍然指向分配时的位置。这被认为是一种严重的编程错误。但通常情况下,运行环境并不会帮助识别或纠正此类错误。

不要把枪指向自己并扣动扳机!


3
那是未定义的行为,任何事情都可能发生。
free(ptr);
*ptr = 12345;

这是不合法的。它可能会崩溃,或者如果你不幸的话,它可能看起来工作正常,潜在地隐藏问题,直到软件被运行在核电站上。虽然,如果你写这样的代码,你可能不会为这样的公司工作。 :)


我知道这是未定义的行为。但是我试着去做,结果事情开始正常工作了。这就是我问这个问题的原因。 - Rasmi Ranjan Nayak

1

你似乎不理解未定义行为。基本上,这种行为是未定义的。它可以做任何事情,包括但不限于以下几点:

  1. 崩溃
  2. 执行你错误地期望它执行的操作
  3. 执行你指定的操作,但不会产生错误
  4. 在你的控制台上开始一场俄罗斯方块游戏
  5. 重新格式化你的硬盘

通常情况下,在许多系统中,访问已释放内存可能会看起来像它已经工作了,但实际上会随机破坏程序的其他部分认为自己拥有的数据(取决于释放后是否有分配)。

试图定义未定义的行为只会让你陷入困境。最好的方法是一开始就不要这样做。


0

free() 释放指向 *ptr 的内存,但不会更改 *ptr 的值,因此如果该值与其他任何内容不冲突,则仍将正常工作,但是该内存可能会被另一个进程随机分配。通常的做法是执行 free(ptr); ptr = NULL,以避免在没有另一个 malloc 调用的情况下意外重用内存。


在现代的多用户操作系统中,被释放的内存对于程序来说并不会分配给另一个进程。不同进程的内存空间是独立的。 - Eric Postpischil
正确的是 Eric。应该说同一个过程的另一部分。 - Alec Danyshchuk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接