释放malloc分配的内存后仍可访问,未触发segmentation fault的技术疑问
为什么free内存后访问还能正常运行,没触发段错误?
这是C语言里特别容易踩的内存管理坑,我来给你理清楚背后的逻辑:
首先得搞懂free()到底干了什么——它不会立刻清空内存里的数据,也不是马上把这块内存变成你的进程不能碰的禁区。它只是向操作系统发出一个信号:“这块内存我用完了,你可以收回去,之后分给其他需要的地方用”。但在操作系统还没真的把这块内存重新分配出去之前,原来的数据大概率还留在原地,所以你这会儿去读,还能拿到旧值,就像你代码里输出的9一样。
那为啥没触发Segmentation Fault(段错误)呢?段错误是只有当你访问了操作系统明确标记为不可访问的内存区域才会触发的,比如NULL指针,或者已经被系统回收并彻底从你的进程地址空间移除的内存。刚free完的内存,系统还没来得及做这个标记,你的进程暂时还能“碰”到它,但这种行为属于C标准里的未定义行为(Undefined Behavior)——意思就是,程序的结果完全没谱,今天能正常输出,明天可能直接崩溃,换个编译器、操作系统甚至只是改改其他代码,结果都可能不一样。
看你的示例代码:
#include <stdio.h> #include <stdlib.h> int main() { int *arr = (int*)malloc(5*sizeof(int)); arr[0] = 2; arr[4]=9; free(arr); printf("%d\n",arr[4]); // 这里就是访问已释放内存的未定义行为 return 0; }
free(arr)之后,arr就变成了野指针,它指向的内存已经不再属于你的程序了。哪怕这次能读到正确的值,也绝对不能依赖这种情况——万一之后系统把这块内存分配给了其他变量,你再去读就会拿到乱七八糟的数值,甚至修改的话会破坏其他数据,导致莫名其妙的bug。
给你两个实用的建议:
- 每次free完指针后,立刻把它赋值为
NULL:
这样之后如果不小心访问这个指针,就会触发段错误,能帮你快速定位问题,总比默默埋下隐患好。free(arr); arr = NULL; - 从根源上避免:永远不要访问已经被free的内存,这是C编程里的基本准则。
内容的提问来源于stack exchange,提问作者Serofin
相关产品推荐
相关产品推荐

