CSAPP malloc lab

本文档描述了实现自定义内存分配器的过程,采用分离存储的策略,维护16个大小类别的空闲链表。当需要扩展堆时,会检查新块是否能与前一块合并以减少碎片。malloc通过调整请求大小并对其对齐来工作,free则从空闲链表中删除相应块。realloc负责重新分配内存,如果剩余空间足够,则将其分割成新的空闲块,优化内存利用率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

整体的设计:使用分离存储的方案,维护一个存储空闲链表的数组free_block_list,每个大小类一个空闲链表,根据2的幂来划分大小,块的设计采用书本上介绍的显示空闲链表的方案。

当可供使用的空间不够时,就会扩展堆。在extend_heap中会增加堆顶的大小,并将新的空闲块挂载到free_block_list上。为了减少内存碎片,会根据新申请的块的前一个块是否空闲来决定是否与其合并。

void *extend_heap(size_t size)
{
    void *ptr;
    // align
    size = ALIGN(size);
    // 增加堆的大小
    if ((ptr = mem_sbrk(size)) == (void *)-1)
        return NULL;

    // 初始化新申请的空闲块
    PUT(HDRP(ptr), PACK(size, 0));
    PUT(FTRP(ptr), PACK(size, 0));
    /* 注意这个块是堆的结尾,所以还要设置一下结尾 */
    PUT(HDRP(NEXT_BLKP(ptr)), PACK(0, 1));
    // 将新申请的空闲块挂到free_block_list上
    insert_node(ptr, size);
    // 合并空闲块
    return merge_free_block(ptr);
}

insert_node实现了将一个空闲块插入到free_block_list的操作,free_block_list中一共有16条链表,下标由0到15升序排列,free_block_list中的元素指向队列的队尾
。将ptr插入block_free_list,链表从大到小排序,在insert_node中逆序遍历链表查找到对应的位置,将空闲块插入。需要注意的是,当链表为空时free_block_list中对应的元素为NULL。

void insert_node(void *ptr, size_t size)
{
    int idx = 0;
    void *next_node = NULL;
    void *pre_node = NULL;

    // 找到相应的桶
    for (;(idx < FREE_LIST_LENGTH - 1) && (size > 1); size >>= 1)
        idx++;
    next_node = free_block_list[idx];

    // next_node为pre_node的前一个结点
    for (; (next_node != NULL) && (size > GET_SIZE(HDRP(next_node))); next_node = GET_PRED_NODE(next_node))
        pre_node = next_node;

    if (next_node != NULL && pre_node != NULL) {    // case 1
        ASSIGN(GET_PRED_ADDR(ptr), next_node);
        ASSIGN(GET_NEXT_ADDR(next_node), ptr);
        ASSIGN(GET_NEXT_ADDR(ptr), pre_node);
        ASSIGN(GET_PRED_ADDR(pre_node), ptr);
    }
    else if (next_node != NULL && pre_node ==
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值