首页 > 后端开发 > C++ > 正文

实现 malloc() 和 free() — 分割大块

聖光之護
发布: 2024-12-31 17:30:39
原创
972人浏览过

实现 malloc() 和 free() — 分割大块

上一篇文章探讨了内存块重用顺序对内存消耗的影响,并优化了函数以减少浪费。然而,另一个更严重的问题依然存在:一个巨大的内存块可能会占据多个小块本可利用的空间。例如,分配一大块内存,释放后,再分配两个更小的块:

void *ptr1 = abmalloc(128);
void *ptr2 = abmalloc(8);
abfree(ptr1);
void *ptr3 = abmalloc(8);
void *ptr4 = abmalloc(8);
登录后复制

这时,128字节的空闲块无法被8字节的请求利用,导致后续8字节块分配需要再次扩展堆,造成内存利用率低下。

解决这个问题,一种高效但复杂的方法是使用“bins”:按大小分组的块列表。另一种更简单的方案是将大块分割成更小的块。本文采用后者。

代码重构

首先,对代码进行轻微重构。header_new() 函数同时负责分配内存和初始化块头,这不利于代码的可读性和维护性。我们将它拆分成两个函数:

  • header_plug():将已初始化的块插入到前一个和下一个块之间。
  • header_init():初始化块的元数据(大小和可用性)。

它们分别如下:

void header_init(header *header, size_t size, bool available) {
    header->size = size;
    header->available = available;
}

void header_plug(header *header, header *previous, header *next) {
    header->previous = previous;
    if (previous != NULL) {
        previous->next = header;
    }
    header->next = next;
    if (next != NULL) {
        next->previous = header;
    }
}
登录后复制

header_new() 函数修改如下:

header *header_new(header *previous, size_t size, bool available) {
    header *header = sbrk(sizeof(header) + size);
    header_init(header, size, available);
    header_plug(header, previous, NULL);
    return header;
}
登录后复制

(abmalloc() 函数中 last->previous->next = last; 这行可以删除,因为 header_plug() 现在负责处理此逻辑。)

分割内存块

接下来,实现 header_split() 函数。给定一个块头和所需最小大小,如果原始块足够大,则将其分割成两部分:

  • 所需大小的块;
  • 剩余部分及其新的块头;

首先,检查块是否足够大:

header *header_split(header *header, size_t size) {
    size_t original_size = header->size;
    if (original_size >= size + sizeof(header)) {
登录后复制

如果足够大,则分割块。首先,减小当前块的大小:

        header->size = original_size - size - sizeof(header);
登录后复制

计算新块的指针:

        header *new_header = (header + 1) + header->size; // Corrected pointer calculation
登录后复制

初始化新块的头:

        header_init(new_header, size, true);
登录后复制

将新块连接到链表:

        header_plug(new_header, header, header->next);
登录后复制

如果原始块是最后一个块,更新 last 指针:

        if (header == last) {
            last = new_header;
        }
登录后复制

返回新块:

        return new_header;
    } else {
        return header;
    }
}
登录后复制

更新 abmalloc()

最后,修改 abmalloc() 函数,在找到可用块后,调用 header_split() 尝试分割它:

if (header->available && (header->size >= size)) {
    header = header_split(header, size);
    header->available = false;
    return (void*)(header + 1); // Cast to void* for correct return type
}
登录后复制

如果块可以分割,则返回新块;否则,返回原始块。

关于块分割的说明

需要注意的是,新块是在原始块的末尾创建的。虽然也可以在开头创建,但在末尾创建新块可以使新的空闲块更靠近旧块,提高下次 abmalloc() 调用的效率。

分割大块内存是改进内存管理的一步,但它也可能导致小块内存碎片化,从而导致更大的请求需要扩展堆。下一篇文章将探讨如何解决这个问题。

以上就是实现 malloc() 和 free() — 分割大块的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
相关标签:
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号