You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

释放手动分配内存后给指针赋值未报错?求技术解释

为什么free()后使用指针未报错反而能正常运行?

我运行这段C语言代码时,在调用free()释放手动分配的内存后,执行*p = 3490并成功打印出3490,但相关资料指出该操作属于「Use after free()」的未定义行为,本应报错。我编译运行后未发现异常,请问这是为什么?

#include <stdio.h>
#include <stdlib.h>

int main()
{
    // Allocate space for a single int (sizeof(int) bytes-worth):
    int *p = malloc(sizeof(int));

    *p = 12; // Store something there
    printf("%d\n", *p); // Print it: 12

    free(p); // All done with that memory

    *p = 3490;          // ERROR: undefined behavior! Use after free()!
    printf("%d\n", *p); // Print it: 3490
}

核心原因:未定义行为≠一定会报错

C标准里的「未定义行为」(Undefined Behavior),意思是标准不对这种操作的结果做任何保证,它可能正常运行、可能崩溃、可能输出乱码、甚至可能破坏其他程序的数据——但绝对不是「必须报错」。你这次能正常运行,只是巧合,具体原因有这几点:

  1. 内存未被立刻覆写或回收
    调用free()后,内存分配器通常不会马上把这块内存还给操作系统,而是把它放进自己管理的空闲内存池里,等待下一次malloc请求。在这块内存被重新分配给其他变量之前,它的物理地址依然可以被访问,里面的内容也不会被主动修改,所以你写入3490再读取,暂时能得到正确结果。

  2. 未触发内存保护机制
    很多操作系统的内存保护是按「内存页」来管理的(比如一页4KB),而你分配的只是一个int(通常4字节),远小于一页的大小。free()后,整个内存页的访问权限不会立刻被修改,所以你的读写操作不会触发段错误(Segmentation Fault)。

  3. 编译器优化的影响
    如果你开启了较高等级的编译优化(比如-O2),编译器可能会识别出这是未定义行为,直接优化掉后续的读写操作,或者让程序出现更奇怪的结果——但默认编译选项下,编译器可能不会做这么激进的处理。


重要提醒:这种「正常运行」完全不可靠,换个环境、加几行代码、甚至只是重启程序,结果都可能完全不同。永远不要依赖未定义行为的表现,写代码时一定要避免Use after free这类问题。

内容的提问来源于stack exchange,提问作者Mathology

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 09:12:55