sle*_*lee 9 c free memory-management
可能重复:
malloc()和free()如何工作
#include <stdio.h>
#include <stdlib.h>
int * alloc()
{
int *p = (int *)calloc(5,4);
printf("%d\n",p);
return p;
}
int main()
{
int *p = alloc();
free(p);
printf("%d\n",p);
p[0] = 1;
p[1] = 2;
printf("%d %d\n",p[0],p[1]);
}
Run Code Online (Sandbox Code Playgroud)
至于代码段,我先分配5个整数.然后我释放了记忆.当我打印p时,为什么p sill的值与首先分配的内存地址相同?我也可以为p [0]和p [1]赋值.这是否意味着free()什么都不做?一旦我分配了内存,我可以稍后使用虽然我已经释放了它.
Mat*_*hen 14
free释放内存在该地址.它不会改变p变量本身.但是,在此p之后做任何事情都是未定义的行为.如果你在释放后立即使用它似乎可行,但它仍然完全错误,并可能导致崩溃或更糟.
free是特定于实现的.但是,在大多数实现中,它将写入堆中的簿记数据,以指示内存现在可用.例如,它可能将特定块标记为未使用,或者将块与相邻的空块组合.
请注意,使用%d指针也是未定义的.
内存只能以页面为单位从程序中删除,甚至不太可能被观察到.
如果需要,calloc(3)和malloc(3)确实与内核交互以获取内存.但是大多数free(3)的实现都没有将内存返回给内核1,它们只是将它添加到一个空闲列表中,calloc()和malloc()稍后会参考,以便重用已发布的块.
即使free()想要将内存返回给系统,它也需要至少一个连续的内存页才能让内核真正保护该区域,因此释放一个小块只会导致保护更改,如果它是页面中的最后一个小块.
所以你的街区就在那里,坐在免费清单上.您可以像访问它一样访问它.C直接编译为机器代码,没有特殊的调试安排,在加载和存储上没有健全性检查.现在,如果您尝试访问一个空闲块,标准就不会定义该行为,以免对库实现者提出不合理的要求.有各种各样的事情可能会出错:
1.很少有free()实现尝试将内存返回系统的事实不一定是由于实现者的松弛.与内核交互比简单地执行库代码慢得多,而且好处很小.大多数程序具有稳态或增加的内存占用,因此分析堆寻找可返回内存所花费的时间将完全被浪费.其他原因包括内部碎片使页面对齐的块不太可能存在,并且返回块可能会将块分块到任何一侧.最后,几个返回大量内存的程序可能会绕过malloc()并简单地分配和释放页面.
从技术上来说
p[0] = 1;
p[1] = 2;
Run Code Online (Sandbox Code Playgroud)
当您尝试使用悬空指针时,调用未定义的行为(这意味着任何事情都可能发生) 。 p
此外,迂腐甚至printf("%d\n",p);调用 UB (格式说明符和参数类型不匹配printf())