c实现的内存池

中间用简单链表就可以,效率不错,分配时比老程的快,没有详细测试。
做全局的分配释放函数,可以像sgi stl中那样建16个全局的内存池,释放时还可以提供一个带大小的函数以提高效率。
新的block放在链表首部,对连续的new有利,对后new先delete有利。

做成环链表的好处是成功回收空间后,让blocklist指向该block,这样下次分配时就不用遍历blocklist了。删除时如果块回收之后全部空闲应释放块。分配空间时也应更新blocklist。这个先记下来。

频繁使用字符串造成内存碎片用内存池就可以解决,只是要记录其长度。
在c++中如果使用泛型的内存池(虽然看起来很有技巧),通用性不好,不能动态指定内存池,一次性分配多个对象不会调用内存池分配,不适合使用字符串,简单数据类型(必须继承),而且类都必须继承这个池。

至于alloc和free的线程安全,每个池加锁即可,这样在多线程环境下内存池的效率应该更具优越性。

SGI的内存池是全局的,因为不记录各个块(统一交给退出程序时释放),控制简单,内存利用充分,分配和释放都十分快速。但有一个不好的是,一旦程序占用了内存就不释放。

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

typedef struct hat_mempool hat_mempool;
typedef struct hat_mempool_block hat_mempool_block;
typedef struct hat_mempool_unit hat_mempool_unit;

struct hat_mempool
{
long unit_size;
long block_size;
hat_mempool_block* block_list;
};

struct hat_mempool_block
{
hat_mempool_unit* free_list;
hat_mempool_block* next;
char data[1];
};

struct hat_mempool_unit
{
hat_mempool_unit* next;
};

void hat_mempool_init(hat_mempool* pool, long unit_size, long block_size)
{
pool->unit_size = (unit_size + 3) & 0xfffffffc;/*按4字节对齐*/
pool->block_size = block_size;
pool->block_list = NULL;
}

void hat_mempool_term(hat_mempool* pool)
{
hat_mempool_block *block = pool->block_list, *tmp;
while (block)
{
tmp = block->next;
free(block);
block = tmp;
}
}

void* hat_mempool_alloc(hat_mempool* pool)
{
hat_mempool_block *block = pool->block_list, **ppblock = &pool->block_list;
hat_mempool_unit *unit;
long i;

while (block)
{
if (block->free_list)
{
unit = block->free_list;
block->free_list = unit->next;
return unit;
}
block = block->next;
}

block = malloc(pool->block_size * pool->unit_size + 8);
if (!block)
{
return NULL;
}

*ppblock = block;
unit = block->free_list = (hat_mempool_unit*)(block->data + pool->unit_size);
block->next = NULL;

for (i = 2; i < pool->block_size; ++i,unit = unit->next)
{
unit->next = (hat_mempool_unit*)((char*)unit + pool->unit_size);
}
unit->next = NULL;

return block->data;
}

void hat_mempool_free(hat_mempool *pool, void* ptr)
{
hat_mempool_block *block = pool->block_list;
hat_mempool_unit *unit;
long ptrdiff;

while (block)
{
ptrdiff = (long)((char*)ptr - block->data);
if (ptrdiff >= 0 && ptrdiff < pool->unit_size * pool->block_size)
{
if (ptrdiff % pool->unit_size)
{
return;
}
for (unit = block->free_list; unit; unit = unit->next)
{
if (unit == ptr)
{
return;
}
}

unit = block->free_list;
block->free_list = ptr;
((hat_mempool_unit*)ptr)->next = unit;
return;
}

block = block->next;
}
}

#define ALLOC_TIMES 1000000
int main()
{
clock_t pre;
long i;
hat_mempool pool;

hat_mempool_init(&pool, sizeof(long), 20);
pre = clock();
for (i = 0; i < ALLOC_TIMES; ++i)
{
hat_mempool_alloc(&pool);
}

printf("mem pool use %d clocks./n", clock() - pre);

hat_mempool_term(&pool);
scanf("%d", &i);
return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下载时请看下面说明,对写一个动态的内存池很有帮助。 这是一个用C++语言链表的方法实现的一个静态内存池代源码。原理就是先向系统申请一块大内存,然后把这一大块分隔成相等的很多小块,然后在这这些小块的首地址部份放一个结构体,结构体中有一个值是用来标明这一小块是否使用中。在这里存放你要放存的数据就是用结构体首地址加结构体自身长度就得到要放数据的首地址了.具体看代码的实现吧。我说一下动态内存池的写法。那是我给公司写的就不能上传了。结构体和静态内存池的这个差不多一样,只是增加了一个成员用来记录每一节点到大块内存的首地址在到本节点的一个尺寸长度值,做法也是先申请一块大内存。我先从释放说起吧,释放本节点时看自己的相邻节点是不是有释放掉的,如果有则合并掉他们成为一个块,如果碰到相邻的节点是另外的一个大块的话就不用合并了,原因他和自己所在的这一个大块内存上物理地址不是连续,这里一定要记住,释放过程算法怎么去写就看你的了。下面是分配写法要考虑的。在分配一小块内存给高层使用时,如果是分配在尾节点去分配的情况,那好办啊,尾节点如果不够分配了就直接从系统去申请一块大内存,节点连起来在分配,这里有可能会浪费掉一小块以结构体大小的一块内存,如果够分配就直接分配了。如果是在中间节点去分配,这里就要将释放时合并的如果大于现在要分配的就拆开来用,如果拆开剩余的那一部份只有结构体大小就不用在拆开了。这些都是要考虑的东西,优化加快速度就看你自己了.可能看时不些不明白,看静态内存的写法后你就明白了.有时我也要下载其他人共享的东西,所以就一分吧.哈哈~~~~

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值