这个代码是我上个公司工作项目的里面内存管理(基于伙伴算法)的一个简化又简化的版本。
因为没有内存边界检查;
因为没有内存使用统计;
因为没有考虑线程安全;
因为没有内存分配操作的具体文件位置信息;
因为没有考虑内存的浪费;
因为特别简单。。。所以也有一些用处,我定义了最小的内存为8字节,因此可以将任意内存大小散列到8的倍数之内,对于64位的通信系统来说,字节对齐是非常重要的;
mem_pool.h
#ifndef MEM_POOL_H_
#define MEM_POOL_H_ typedef struct MemBlock {
struct MemBlock* next;
int size;
void *ptr;
} MemBlock; typedef unsigned char byte; // 8 16 32 64 128 256 512 1024 2048 4096
// 1 2 4 8 16 32 64 128 256 512
// 0 1 2 3 4 5 6 7 8 9 #define MEM_POOL_MAX 10
#define MEM_BLOCK 8
#define MEM_BLOCK_BASE 8192
#define MEM_BLOCK_TYPE_NUM 10
#define MEM_BLOCK_FREE -1 int mem_pool_index(size_t size);
void mem_pool_init();
void mem_pool_free();
int mem_block_num(size_t size);
MemBlock* mem_block_head_get(size_t size);
void* mem_get(size_t size);
int mem_free(void **ptr); #define mem_ret(ptr) mem_free((void **)&ptr) ////////////////////////////////////////////////////////////////////////// typedef struct MemBlockDlist {
struct MemBlockDlist* prev;
struct MemBlockDlist* next;
int size;
void *ptr;
} MemBlockDlist; void mem_pool_dlist_init();
void mem_pool_dlist_free();
void* mem_realloc(size_t size);
void mem_release(void** ptr); #define mem_alloc(s) mem_realloc(s)
#define mem_relex(p) mem_release((void **)&p) #endif
mem_pool.c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "mem_pool.h" static byte* g_pool_mem[MEM_POOL_MAX] = {};
static MemBlock* g_pool[MEM_POOL_MAX] = {};
const float log2 = log(2.0);
int mem_pool_index(size_t size) {
if (size > && size <= MEM_BLOCK) return ; size_t s = ;
size_t t = size;
size_t i; i = log((float)t)/log2;
17 s = s<<i;
return s == size ? i- : i-;
} MemBlock* mem_block_head(size_t index) {
if (index < || index >= MEM_POOL_MAX)
return NULL; return g_pool[index];
} MemBlock* mem_block_head_get(size_t size) {
if (size > MEM_BLOCK_BASE/ || size <= ) {
printf("size=%d too big to mem pool. using malloc plz\n", size);
return NULL;
}
return mem_block_head(mem_pool_index(size));
} int mem_block_num(size_t size) {
return MEM_BLOCK_BASE/size;// size > 0 is true
} static MemBlock* mem_block_alloc(byte* buf, int block_size, int block_num) {
MemBlock *head, *curr, *next;
int i; head = (MemBlock *)buf;
head->size = MEM_BLOCK_FREE;
head->ptr = (byte*)head + sizeof(MemBlock);
head->next = NULL; curr = head;
for (i=; i<block_num; i++) {
next = (MemBlock*)((byte*)curr + block_size);
next->size = MEM_BLOCK_FREE;
next->ptr = (byte*)next + sizeof(MemBlock);
curr->next = next;
next->next = NULL;
curr = next;
}
return head;
} void mem_pool_init() {
size_t l, i, s, n, b;
for (l=; l<MEM_BLOCK_TYPE_NUM; l++) {
i = 1 << l;
b = i * MEM_BLOCK;
s = b + sizeof(MemBlock);
n = mem_block_num(b); g_pool_mem[l] = (byte *)malloc(s * n);
if (NULL == g_pool_mem[l]) {
break;
}
g_pool[l] = mem_block_alloc(g_pool_mem[l], s, n);
}
return;
} void mem_pool_free() {
for (int i=; i<MEM_BLOCK_TYPE_NUM; i++) {
if (NULL != g_pool_mem[i]) {
free(g_pool_mem[i]);
g_pool_mem[i] = NULL;
g_pool[i] = NULL;
}
}
return;
} void* mem_get(size_t size) {
MemBlock* head = mem_block_head_get(size);
if (NULL == head) return NULL; do {
if (head->size == MEM_BLOCK_FREE) {
head->size = size;
return head->ptr;
} else {
head = head->next;
}
} while (head->next); return NULL;
} int mem_free(void **ptr) {
if (NULL == ptr || NULL == *ptr) return ; MemBlock *block = (MemBlock *)((byte*)(*ptr) - sizeof(MemBlock));
block->size = MEM_BLOCK_FREE; return ;
}
mem_pool_dlist.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "mem_pool.h" static byte* g_pool_buff[MEM_POOL_MAX] = {};
static MemBlockDlist* g_pool_objects[MEM_POOL_MAX] = {};
static MemBlockDlist* g_pool_freelist[MEM_POOL_MAX] = {};
static MemBlockDlist* g_pool_cursor[MEM_POOL_MAX] = {}; MemBlockDlist* mem_block_dlist_head(size_t index) {
if (index < || index >= MEM_POOL_MAX)
return NULL; return g_pool_objects[index];
} void mem_pool_cursor_init() {
for(size_t i=; i<MEM_POOL_MAX; i++)
g_pool_cursor[i] = mem_block_dlist_head(i);
} static MemBlockDlist* mem_block_dlist_alloc(byte* buf, int bk_size, int bk_num){
MemBlockDlist *head, *curr, *next;
int i; head = (MemBlockDlist *)buf;
head->size = MEM_BLOCK_FREE;
head->ptr = (byte*)head + sizeof(MemBlockDlist);
head->prev = NULL;
head->next = NULL; curr = head;
for (i=; i<bk_num; i++) {
next = (MemBlockDlist*)((byte*)curr + bk_size);
next->size = MEM_BLOCK_FREE;
next->ptr = (byte*)next + sizeof(MemBlockDlist); curr->next = next;
next->prev = curr;
next->next = NULL; curr = next;
}
return head;
} void mem_pool_dlist_init() {
size_t l, i, s, n, b;
for (l=; l<MEM_BLOCK_TYPE_NUM; l++) {
i = 1 << l;
b = i * MEM_BLOCK;
s = b + sizeof(MemBlockDlist);
n = mem_block_num(b); g_pool_buff[l] = (byte *)malloc(s * n);
if (NULL == g_pool_buff[l]) {
break;
}
g_pool_objects[l] = mem_block_dlist_alloc(g_pool_buff[l], s, n);
} mem_pool_cursor_init();
} void mem_pool_dlist_free() {
for (int i=; i<MEM_BLOCK_TYPE_NUM; i++) {
if (NULL != g_pool_buff[i]) {
free(g_pool_buff[i]); g_pool_buff[i] = NULL;
g_pool_objects[i] = NULL;
g_pool_freelist[i] = NULL;
g_pool_cursor[i] = NULL;
}
}
} MemBlockDlist* mem_free_block_get(int index) {
if (index < || index >= MEM_POOL_MAX) return NULL; MemBlockDlist* tmp = g_pool_freelist[index];
if (!tmp) return NULL; g_pool_freelist[index] = tmp->next;
g_pool_freelist[index]->prev = NULL;
tmp->next = NULL; return tmp;
} void* mem_realloc(size_t size) {
int index = mem_pool_index(size);
if (index < || index >= MEM_POOL_MAX)
return NULL; MemBlockDlist* ptr = mem_free_block_get(index);
if (ptr) {
ptr->size = size;
return ptr->ptr;
} MemBlockDlist* cursor = g_pool_cursor[index];
if (NULL == cursor) {
printf("pool index=%d memory leak or queue is all used.\n", index);
return NULL;
} if (MEM_BLOCK_FREE == cursor->size) {
g_pool_cursor[index] = cursor->next;
cursor->size = size;
return cursor->ptr;
} return NULL;
} void mem_release(void** ptr) {
if (NULL == ptr || NULL == *ptr)
return; size_t len = sizeof(MemBlockDlist);
MemBlockDlist *block = (MemBlockDlist *)((byte*)(*ptr) - len); int index = mem_pool_index(block->size);
if (index < || index >= MEM_POOL_MAX)
return; memset((byte*)(*ptr), , block->size);
MemBlockDlist* top = g_pool_freelist[index]; g_pool_freelist[index] = block;
if (top) {
g_pool_freelist[index]->next = top;
} g_pool_freelist[index]->size = MEM_BLOCK_FREE;
}