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

最新文章

  1. [MFC] MFC 查找其他窗口句柄 操作其他窗口
  2. 当ListView有Header时,onItemClick里的position不正确
  3. hihocoder 1169 猜数字
  4. [jobdu]用两个栈实现队列
  5. Js,alert出现乱码问题,赶紧记下来,额~~~
  6. apt
  7. php中__clone() shallow copy 只是浅复制
  8. Python 基础之函数、深浅copy,set及练习
  9. 指针变量的*p,p以及&p的区别
  10. 浅谈python中的闭包函数
  11. 3行代码快速实现Spring Boot Oauth2服务
  12. 理解 Linux 中 `ls` 的输出
  13. flutter 主题切换
  14. 《Unbroken》
  15. Vue + Element UI 实现权限管理系统(动态加载菜单)
  16. 跨过Django的坑
  17. # Writing your first Django app, part 2
  18. windows系统下构建Jenkins持续集成
  19. rtesseract的例子
  20. 用python给图片添加文字(水印)

热门文章

  1. C - C工程编译那些事【configure-make || cmake-make】
  2. 鸟哥的linux私房菜——第十六章学习(程序管理与 SELinux 初探)
  3. JS编程练习:封装insertAfter函数(功能类似于系统insertBefor)
  4. HDU 4511 小明系列故事——女友的考验 (AC自动机 + DP)题解
  5. java变量、数据类型、运算符
  6. Get your site working on Google Search Console , 在 Google Search Console中运行您的网站, Google Search Console
  7. Apple Watch Series 6 字母图案 (图解教程)
  8. js with All In One
  9. 如何用 js 实现一个 new 函数
  10. js 垃圾回收 & js GC