如何自己实现 malloc

实现自己的 malloc 函数是一个深入理解内存管理的好方法。下面我将介绍一个简单的 malloc 实现思路和步骤。

基本原理

  1. 内存分配策略:通常使用链表来管理空闲内存块
  2. 内存块结构:每个内存块需要包含元数据(大小、是否空闲等)和实际数据区
  3. 分配算法:首次适应(first-fit)、最佳适应(best-fit)或最差适应(worst-fit)

简单实现步骤

1. 定义内存块结构

typedef struct block {
    size_t size;        // 块大小(不包括元数据)
    int free;           // 是否空闲(1=空闲, 0=占用)
    struct block *next; // 指向下一个块
    // 实际数据区紧随其后
} block_t;

2. 定义全局变量

#define HEAP_SIZE 1024 * 1024 // 1MB堆空间
static char heap[HEAP_SIZE];  // 模拟堆内存

block_t *free_list = (block_t *)heap; // 空闲链表头

3. 初始化堆

void init_heap() {
    free_list->size = HEAP_SIZE - sizeof(block_t);
    free_list->free = 1;
    free_list->next = NULL;
}

4. 实现 malloc

void *my_malloc(size_t size) {
    if (size <= 0) return NULL;
    
    block_t *current = free_list;
    block_t *best_fit = NULL;
    
    // 最佳适应算法: 寻找最小的足够大的空闲块
    while (current) {
        if (current->free && current->size >= size) {
            if (!best_fit || current->size < best_fit->size) {
                best_fit = current;
                // 如果大小正好,可以提前终止搜索
                if (best_fit->size == size) break;
            }
        }
        current = current->next;
    }
    
    if (best_fit) {
        // 检查是否可以分割块
        if (best_fit->size > size + sizeof(block_t) + 1) {
            // 创建新块
            block_t *new_block = (block_t *)((char *)best_fit + sizeof(block_t) + size);
            new_block->size = best_fit->size - size - sizeof(block_t);
            new_block->free = 1;
            new_block->next = best_fit->next;
            
            best_fit->size = size;
            best_fit->next = new_block;
        }
        
        best_fit->free = 0;
        return (void *)(best_fit + 1); // 返回数据区指针
    }
    
    return NULL; // 没有足够空间
}

5. 实现 free

void my_free(void *ptr) {
    if (!ptr) return;
    
    block_t *block = (block_t *)ptr - 1;
    block->free = 1;
    
    // 合并相邻的空闲块
    block_t *current = free_list;
    while (current) {
        if (current->free && current->next && current->next->free) {
            current->size += sizeof(block_t) + current->next->size;
            current->next = current->next->next;
        }
        current = current->next;
    }
}

优化方向

  1. 内存对齐:确保返回的指针正确对齐(通常是8字节对齐)
  2. 线程安全:添加锁机制使分配器线程安全
  3. 性能优化:使用更高效的数据结构(如分离空闲链表)
  4. 碎片整理:定期合并碎片
  5. 扩展堆空间:当内存不足时通过系统调用(sbrk/mmap)请求更多内存

完整示例注意事项

这只是一个简化示例,实际实现需要考虑更多因素:

  • 错误处理
  • 多线程环境
  • 内存对齐要求
  • 性能优化
  • 与操作系统交互获取更多内存

实现一个生产级别的 malloc 要复杂得多,但以上代码展示了基本概念。