073. 编写代码实现简单的内存池

内存池(Memory Pool)是一种高效的内存管理技术,用于预先分配一块较大的内存区域,并从中分配和回收小块内存。内存池可以显著减少动态内存分配的开销,提高程序的性能,尤其是在频繁分配和释放小块内存的场景中。

1. 内存池的实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 定义内存池结构
typedef struct MemoryPool {
    char* pool;          // 内存池的起始地址
    size_t poolSize;     // 内存池的总大小
    size_t blockSize;    // 每个内存块的大小
    int numBlocks;       // 内存池中的块数
    int* freeList;       // 空闲块的链表
    int freeCount;       // 空闲块的数量
} MemoryPool;

// 初始化内存池
void initMemoryPool(MemoryPool* pool, size_t poolSize, size_t blockSize) {
    pool->pool = (char*)malloc(poolSize);
    if (pool->pool == NULL) {
        printf("内存分配失败!\n");
        exit(1);
    }
    pool->poolSize = poolSize;
    pool->blockSize = blockSize;
    pool->numBlocks = poolSize / blockSize;
    pool->freeList = (int*)malloc(pool->numBlocks * sizeof(int));
    if (pool->freeList == NULL) {
        printf("内存分配失败!\n");
        exit(1);
    }
    for (int i = 0; i < pool->numBlocks; i++) {
        pool->freeList[i] = i;
    }
    pool->freeCount = pool->numBlocks;
}

// 从内存池中分配内存
void* allocateFromPool(MemoryPool* pool) {
    if (pool->freeCount == 0) {
        printf("内存池已满,无法分配更多内存!\n");
        return NULL;
    }
    int index = pool->freeList[--pool->freeCount];
    return pool->pool + index * pool->blockSize;
}

// 将内存返回到内存池
void freeToPool(MemoryPool* pool, void* ptr) {
    int index = (char*)ptr - pool->pool;
    if (index < 0 || index >= pool->poolSize || (index % pool->blockSize != 0)) {
        printf("无效的指针!\n");
        return;
    }
    index /= pool->blockSize;
    pool->freeList[pool->freeCount++] = index;
}

// 销毁内存池
void destroyMemoryPool(MemoryPool* pool) {
    free(pool->pool);
    free(pool->freeList);
    pool->pool = NULL;
    pool->poolSize = 0;
    pool->blockSize = 0;
    pool->numBlocks = 0;
    pool->freeList = NULL;
    pool->freeCount = 0;
}

int main() {
    MemoryPool pool;
    initMemoryPool(&pool, 1024, 64); // 初始化内存池,总大小1024字节,每个块64字节

    void* block1 = allocateFromPool(&pool);
    void* block2 = allocateFromPool(&pool);
    printf("分配的内存块1: %p\n", block1);
    printf("分配的内存块2: %p\n", block2);

    freeToPool(&pool, block1);
    printf("释放内存块1\n");

    void* block3 = allocateFromPool(&pool);
    printf("重新分配的内存块1: %p\n", block3);

    destroyMemoryPool(&pool); // 销毁内存池
    return 0;
}

2. 代码说明

内存池结构

  • pool:内存池的起始地址。

  • poolSize:内存池的总大小。

  • blockSize:每个内存块的大小。

  • numBlocks:内存池中的块数。

  • freeList:空闲块的链表。

  • freeCount:空闲块的数量。

初始化内存池

  • 分配内存池的总内存。

  • 初始化空闲块链表,将所有块标记为可用。

分配内存

  • 从空闲块链表中取出一个块。

  • 返回该块的地址。

释放内存

  • 将释放的块的索引添加到空闲块链表中。

销毁内存池

  • 释放内存池的总内存和空闲块链表。

3. 示例运行

输入:

无输入

输出:

分配的内存块1: 0x12345678
分配的内存块2: 0x123456b8
释放内存块1
重新分配的内存块1: 0x12345678

4. 注意事项

  1. 内存对齐:确保内存块的大小满足对齐要求,以提高访问效率。
  2. 内存池大小:内存池的总大小和块大小应根据实际需求进行调整。
  3. 线程安全:在多线程环境中,需要对内存池的操作进行同步,以避免竞态条件。
  4. 错误处理:在分配和释放内存时,应进行错误检查,确保操作的合法性。

5. 总结

内存池是一种高效的内存管理技术,适用于频繁分配和释放小块内存的场景。通过实现一个简单的内存池,可以显著减少动态内存分配的开销,提高程序的性能。在实际应用中,可以根据具体需求对内存池进行优化和扩展。

视频讲解

BiliBili: 视睿网络-哔哩哔哩视频 (bilibili.com)