malloc和free解析
2024-10-19 07:09:10
malloc和free都是库函数,调用系统函数sbrk()来分配内存。除了分配可使用的内存以外,还分配了”控制“信息,这有点像内存池常用的手段。并且,分配的内存是连续的。
1. malloc
#include
void malloc_init()
{
last_valid_address = sbrk(0);//从操作系统分配内存
managed_memory_start = last_valid_address;//设置全局变量
has_initialized = 1;//全局变量,标示已经被初始化
}
上面那个函数,从名字中就可以理解,是一个初始化函数。什么时候来初始化呢?我想应该是在自己的程序里第一次调用这个函数时会调用到malloc_init()。如果存在多次调用,则会走下面这个函数:
这个是分配内存的控制块:
struct mem_control_block {
int is_available;//为0或1,等于1时表示可以重复使用
int size;//内存块的大小,包括本结构体在内
};
//清单 6. 主分配程序
void *malloc(long numbytes) {
void *current_location;//无类型指针,表示“当前块”,后面可以知道,它相关于链表访问时,操作当前节点的指针
struct mem_control_block *current_location_mcb;//“当前块”的mem_control_block指针 void *memory_location;//真正会返回的地址指针,即malloc()返回的
if(! has_initialized) {//如果没有初始化,则调用该函数,第一次肯定没有初始化,故,该函数应该会在第一次调用malloc()时使用
malloc_init();
}
numbytes = numbytes + sizeof(struct mem_control_block);//调整传进来的大小,包括mem_control_block这个结构体大小
memory_location = 0;//设置为0 current_location = managed_memory_start;//managed_memory_start为全局变量,保存一块连续内存的起始位置。它第一次在malloc_init()中设置
while(current_location != last_valid_address)//这里开始“遍历”,从managed_memory_start直到last_valid_address
{
current_location_mcb =(struct mem_control_block *)current_location;//无类型指针转换为mem_control_block指针
if(current_location_mcb->is_available)//如果当前块可用。这里is_available为1表示可用
{
if(current_location_mcb->size >= numbytes)//如果当前块的大小足够使用的
{
current_location_mcb->is_available = 0;//标示当前块已经被“占用”了
break;//跳出while表示找到了可用的块,其实是为了节约内存空间
}
}
current_location = current_location +current_location_mcb->size;//走到这里表示“当前块”不可用,current_location往后走“一块”的大小。
} //没有找到,则开辟新的内存
if(! memory_location)
{
sbrk(numbytes);//调用系统函数,分配内存 memory_location = last_valid_address;//这里的memory_location等于last_valid_address,我觉得应该是sbrk()这个系统调用所分配的新的块是与当前块连续的,同时,last_valid_address指向的是所有可用内存的“最后的边界”
last_valid_address = last_valid_address + numbytes;//更新这个“边界” current_location_mcb = memory_location;//设置指针和结构体的值
current_location_mcb->is_available = 0;
current_location_mcb->size = numbytes;
} memory_location = memory_location + sizeof(struct mem_control_block);//指针“跳过”结构体大小,指向真正的可用内存,也就是malloc返回的指针 return memory_location;
}
2.free
void free(void *firstbyte) {
struct mem_control_block *mcb;
mcb = firstbyte - sizeof(struct mem_control_block);//指针后退,退过mem_control_block的大小
mcb->is_available = 1;//标示该“块”可用 return;
}
free函数很简单,就是将当前可用指针后退到真正的“块”的起始位置,再设置“块”为可用(is_available=1),可见free也并不是把内存真正的释放掉了,只是作为标记。为什么要这样设置?从代码中可用看到,这样设置完之后,如果下次再调用malloc,将对所有的块进行搜索,找到这样一个可用的。这样的好处是什么?节约内存!相当于内存池里的重复利用。
参考资料:http://lklkdawei.blog.163.com/blog/static/32574109200881445518891/
http://blog.csdn.net/eroswang/article/details/4265024
最新文章
- [MFC] MFC 查找其他窗口句柄 操作其他窗口
- 当ListView有Header时,onItemClick里的position不正确
- hihocoder 1169 猜数字
- [jobdu]用两个栈实现队列
- Js,alert出现乱码问题,赶紧记下来,额~~~
- apt
- php中__clone() shallow copy 只是浅复制
- Python 基础之函数、深浅copy,set及练习
- 指针变量的*p,p以及&;p的区别
- 浅谈python中的闭包函数
- 3行代码快速实现Spring Boot Oauth2服务
- 理解 Linux 中 `ls` 的输出
- flutter 主题切换
- 《Unbroken》
- Vue + Element UI 实现权限管理系统(动态加载菜单)
- 跨过Django的坑
- # Writing your first Django app, part 2
- windows系统下构建Jenkins持续集成
- rtesseract的例子
- 用python给图片添加文字(水印)
热门文章
- C - C工程编译那些事【configure-make || cmake-make】
- 鸟哥的linux私房菜——第十六章学习(程序管理与 SELinux 初探)
- JS编程练习:封装insertAfter函数(功能类似于系统insertBefor)
- HDU 4511 小明系列故事——女友的考验 (AC自动机 + DP)题解
- java变量、数据类型、运算符
- Get your site working on Google Search Console , 在 Google Search Console中运行您的网站, Google Search Console
- Apple Watch Series 6 字母图案 (图解教程)
- js with All In One
- 如何用 js 实现一个 new 函数
- js 垃圾回收 &; js GC