文末附完整源代码
本内存池管理器旨在提供一种高效的内存管理机制,通过预分配固定大小的内存块,避免频繁的内存分配和释放操作,减少内存碎片,提升程序性能。适用于需要高频次分配/释放相同大小内存块的场景,如网络服务器、嵌入式系统等。
malloc
和 free
操作。MemoryPool
typedef struct MemoryPool {
size_t block_size; // 每个内存块的总大小(含管理头)
size_t total_blocks; // 内存池总块数
size_t free_count; // 当前空闲块数
void* free_list; // 空闲链表头指针
char data[]; // 柔性数组,存储实际内存块
} MemoryPool;
每个内存块前 sizeof(void*)
字节用于存储链表指针(next
),用户可用内存从 block + sizeof(void*)
开始,大小为 block_size - sizeof(void*)
。
MemoryPool* create_memory_pool(size_t user_block_size, size_t num_blocks);
num_blocks
个大小为 user_block_size
的内存块。user_block_size
:用户请求的内存块大小(需满足 user_block_size + sizeof(void*) <= block_size
)。num_blocks
:内存池中内存块的总数。NULL
。void* mem_pool_alloc(MemoryPool* pool);
pool
指向内存池的指针。NULL
。void mem_pool_free(MemoryPool* pool, void* ptr);
pool
指向内存池的指针。ptr
要释放的内存块指针(必须来自 mem_pool_alloc
)。void mem_pool_reset(MemoryPool* pool);
pool
指向内存池的指针。void destroy_memory_pool(MemoryPool* pool);
pool
指向内存池的指针。在 create_memory_pool
中,将预分配的内存块逐个连接成链表。每个块的前 sizeof(void*)
字节存储下一个块的地址。
for (size_t i = 0; i < num_blocks; ++i) {
void* block = pool->data + i * pool->block_size;
*((void**)block) = pool->free_list;
pool->free_list = block;
}
block
。block->next
。block + sizeof(void*)
作为用户内存指针。block = ptr - sizeof(void*)
。mem_pool_reset
重新初始化空闲链表,将所有内存块重新链接到链表中,实现快速批量释放。
user_block_size
必须满足 user_block_size >= sizeof(void*)
,否则无法存储链表指针。mem_pool_alloc
分配的内存,跨池释放会导致未定义行为。操作 | 时间复杂度 | 说明 |
---|---|---|
mem_pool_alloc | O(1) | 直接取出链表头节点 |
mem_pool_free | O(1) | 插入链表头部 |
mem_pool_reset | O(n) | 重建链表,n 为总块数 |
destroy_pool | O(1) | 释放整个内存池 |
内存池通过固定大小分配和链表管理,确保无内存碎片,适合高频次分配/释放场景。
D:\CODING\cyyzwsq\MemoryPool\cmake-build-debug\MemoryPool.exe
=== 内存池测试 ===
Allocated block 0 at 000001fd2ede1940
Allocated block 1 at 000001fd2ede18b8
Allocated block 2 at 000001fd2ede1830
Allocated block 3 at 000001fd2ede17a8
Allocated block 4 at 000001fd2ede1720
Freeing block 0
Resetting memory pool
Allocated block 0 at 000001fd2ede1940
Allocated block 1 at 000001fd2ede18b8
Allocated block 2 at 000001fd2ede1830
Allocated block 3 at 000001fd2ede17a8
Allocated block 4 at 000001fd2ede1720
Destroying memory pool
=== 测试结束 ===
进程已结束,退出代码为 0
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 内存池结构体
typedefstruct MemoryPool {
size_t block_size; // 每个内存块的总大小(含管理头)
size_t total_blocks; // 内存池总块数
size_t free_count; // 当前空闲块数
void* free_list; // 空闲链表头指针
char data[]; // 柔性数组,存储实际内存块
} MemoryPool;
/**
* 创建内存池
* @param user_block_size 用户请求的内存块大小
* @param num_blocks 内存池中内存块的总数
* @return 成功返回内存池指针,失败返回 NULL
*/
MemoryPool* create_memory_pool(size_t user_block_size, size_t num_blocks) {
// 检查参数合法性
if (user_block_size == 0 || num_blocks == 0) {
returnNULL;
}
// 每个块至少要能容纳一个指针(用于空闲链表)
size_t actual_block_size = user_block_size + sizeof(void*);
size_t pool_size = sizeof(MemoryPool) + actual_block_size * num_blocks;
// 分配内存池结构体及内存块空间
MemoryPool* pool = (MemoryPool*)malloc(pool_size);
if (!pool) {
returnNULL;
}
// 初始化内存池字段
pool->block_size = actual_block_size;
pool->total_blocks = num_blocks;
pool->free_count = num_blocks;
pool->free_list = NULL;
// 初始化空闲链表
for (size_t i = 0; i < num_blocks; ++i) {
void* block = pool->data + i * actual_block_size;
*((void**)block) = pool->free_list;
pool->free_list = block;
}
return pool;
}
/**
* 从内存池中分配一个内存块
* @param pool 内存池指针
* @return 成功返回内存块指针,失败返回 NULL
*/
void* mem_pool_alloc(MemoryPool* pool) {
if (!pool || !pool->free_list || pool->free_count == 0) {
returnNULL;
}
void* block = pool->free_list;
pool->free_list = *((void**)block);
pool->free_count--;
// 返回用户可用内存起始地址(跳过链表指针)
return (char*)block + sizeof(void*);
}
/**
* 将内存块释放回内存池
* @param pool 内存池指针
* @param ptr 要释放的内存块指针(必须来自 mem_pool_alloc)
*/
void mem_pool_free(MemoryPool* pool, void* ptr) {
if (!pool || !ptr) {
return;
}
// 计算原始块地址(回退 sizeof(void*) 字节)
void* block = (char*)ptr - sizeof(void*);
// 插入空闲链表头部
*((void**)block) = pool->free_list;
pool->free_list = block;
pool->free_count++;
}
/**
* 重置内存池,将所有内存块重新标记为空闲
* @param pool 内存池指针
*/
void mem_pool_reset(MemoryPool* pool) {
if (!pool) {
return;
}
// 重新构建空闲链表
pool->free_count = pool->total_blocks;
pool->free_list = NULL;
for (size_t i = 0; i < pool->total_blocks; ++i) {
void* block = pool->data + i * pool->block_size;
*((void**)block) = pool->free_list;
pool->free_list = block;
}
}
/**
* 销毁内存池
* @param pool 内存池指针
*/
void destroy_memory_pool(MemoryPool* pool) {
if (pool) {
free(pool);
}
}
// =============================
// 测试用例
// =============================
int main() {
printf("=== 内存池测试 ===\n");
// 创建内存池:每个块大小为 128 字节,共 10 个块
MemoryPool* pool = create_memory_pool(128, 10);
if (!pool) {
printf("Failed to create memory pool\n");
return-1;
}
// 分配 5 个内存块
void* blocks[5];
for (int i = 0; i < 5; ++i) {
blocks[i] = mem_pool_alloc(pool);
if (blocks[i]) {
printf("Allocated block %d at %p\n", i, blocks[i]);
} else {
printf("Allocation failed for block %d\n", i);
}
}
// 释放第一个块
printf("Freeing block 0\n");
mem_pool_free(pool, blocks[0]);
// 重置内存池(释放所有块)
printf("Resetting memory pool\n");
mem_pool_reset(pool);
// 再次分配 5 个块
for (int i = 0; i < 5; ++i) {
blocks[i] = mem_pool_alloc(pool);
if (blocks[i]) {
printf("Allocated block %d at %p\n", i, blocks[i]);
} else {
printf("Allocation failed for block %d\n", i);
}
}
// 销毁内存池
printf("Destroying memory pool\n");
destroy_memory_pool(pool);
printf("=== 测试结束 ===\n");
return0;
}
本内存池管理器通过固定大小内存块和空闲链表管理,实现了高效的内存分配与释放。适用于需要高性能、低延迟的场景,且能有效避免内存碎片问题。