new与malloc

强颜欢笑 提交于 2020-01-13 13:20:20

首先将new与malloc的区别总结如下:

1 new可以自动计算需要分配多大的内存,而malloc必须指明。

2 new返回的指针是有类型的,malloc返回void*类型的指针。

3 new在分配内存的同时会调用构造函数。

4 new是c++运算符,malloc是标准库函数。

由于3所述,malloc在c++中无法满足为非内部对象分配内存的需求。

 

    那么malloc是如何进行内存分配的呢?它将内存块连接为一个链表。调用malloc函数时,它沿链表寻找一个大到足以满足用户请求所需要的空闲内存块。然后,将该内存块传给用户(如果该内存块比用户申请的内存大很多,可进行分割),并将该内存块标记为已用。(free的过程待补充)

    malloc具体实现参考:

http://blog.codinglabs.org/articles/a-malloc-tutorial.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;
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!