首先将new与malloc的区别总结如下:
1 new可以自动计算需要分配多大的内存,而malloc必须指明。
2 new返回的指针是有类型的,malloc返回void*类型的指针。
3 new在分配内存的同时会调用构造函数。
4 new是c++运算符,malloc是标准库函数。
由于3所述,malloc在c++中无法满足为非内部对象分配内存的需求。
那么malloc是如何进行内存分配的呢?它将内存块连接为一个链表。调用malloc函数时,它沿链表寻找一个大到足以满足用户请求所需要的空闲内存块。然后,将该内存块传给用户(如果该内存块比用户申请的内存大很多,可进行分割),并将该内存块标记为已用。(free的过程待补充)
malloc具体实现参考:
.html
该文对Linux系统内存相关知识的介绍也十分清楚。现将其malloc实现简单总结如下:
内存按块划分,每个块由meta区和数据区组成,meta区记录数据区的大小、是否空闲并指向下一个内存块。数据区是真实分配的内存,malloc返回给用户的就是数据区的首地址。首先定义表示内存块的数据结构:
typedef struct s_block* t_block; struct s_block {size_t size;int free;t_block next;int padding;char data[1];};
然后实现查找内存块的find_block,传入需要分配的内存大小,返回找到的指向内存块的指针:
t_block find_block(t_block* last, size_t s) {t_block b = first_block;while (b&&!(b->free && b->size >= s)){*last = b;b = b->next;}return b; }
从头开始搜索链表,对于不符合条件的节点,last立即跟踪,遇到符合条件的节点或空节点循环结束。last是为了当遍历完链表没有符合条件的节点,即b=NULL时,记录最后一个节点,方便后面做扩展。做扩展的代码如下:
#define BLOCKSIZE 24 t_block extend_block(t_block last, size_t s) {t_block b = sbrk(0);if (sbrk(s + BLOCKSIZE) == (void*)-1)return NULL;b->size = s;b->free = 0;b->next = last->next;last->next = b;return b; }
即用系统调用sbrk()在堆上新找到个节点,并将其接到原链表。malloc还要做的一个工作就是如果内存块比较大,将其分给一个申请了很小内存空间的用户会显得很浪费,此时malloc应将该内存块分割,将剩余的内存作为新节点放在链表上:
void split_block(t_block b, size_t s) {t_block newb;newb = (t_block)b->data + s;newb->size = b->size - s - BLOCKSIZE;newb->free = 1;newb->next = b->next;b->next = newb;b->size = s; }
有了以上的函数,malloc就可以简单的实现如下:
void* first_block=NULL;void* malloc(size_t size) {size_t s;s = align(size); t_block b=first_block;t_block last;if (b){b = find_block(&last, s);if (b){if (b->size >= (s + BLOCKSIZE + 8))split_block(b, s);b->free = 0;}else{b = extend_block(last, s);}}else{b = extend_block(NULL, s);first_block = b;}return b; }
转载于:.html
本文发布于:2024-02-04 05:19:17,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170699985252455.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |