用C语言实现的简易内存池

    这套内存池代码其实是我前不久刚刚进公司时,我的师傅安排给我的一个“作业”,可能目的是试探一下我的Coding能力,看看我的编码风格吧。现在把它写在这里和大家分享,这个代码并不是多么高效的内存池,只是作为一个简单的练习,开拓自己的思维,锻炼自己的链表编程能力。所以如果有人想找高效代码用在项目里,我建议还是使用开源的框架比较好。代码如果有BUG请指教,本人小白,大牛勿喷!
    内存池的使用背景:
    1.使用malloc系统函数分配内存虽然很方便,但是很容易产生碎片。
    2.为了使关键模块在需要内存时,避免获取不到内存的麻烦。关键模块创建时,可以预先占用模块所需要的最大 内存,由模块内自行分配释放。
    3.采用预占内存方式的模块,可以明确确定该模块所需要的内存资源大小。有利于硬件资源的确定。
    我的编程思想是建立一个内存池结构体,存储内存池的信息,包括内存块数量、大小、已使用数量、起始地址、终止地址、指向第一个节点的链表指针。

    注释中的所谓节点也是一个结构体,包含内存块指针,节点链表指针。分配内存块时,检测下池中是否有空闲,有则分配,并从池中删去节点,直到释放内存块时再插入链表。

使用完内存池后,释放内存池。这套代码中避免了遍历操作,而且统一开辟、释放内存,可以有效提高效率。


代码如下:

头文件

#ifndef _POOL_H
#define _POOL_H

#include "stdlib.h"
#include "stdio.h"
#include "string.h"

#define LEN sizeof(memblock)//内存块节点大小
#define OPERA_OK  0//操作失败
#define OPERA_ERR 1//操作成功
//内存块节点
typedef struct MEMBLOCK
{
	char* pmem;				//内存指针 
	MEMBLOCK *next;		//指向下一节点的指针
}memblock;
//内存池节点
typedef struct MEMPOOL
{
	int  cnt;								//数量
	int  usedcnt;						//使用个数
	int blocksize;						//内存块大小
	char* firstaddr;					//起始地址
	char* lastaddr;						//结束地址
	MEMBLOCK *firstblock;		//指向下一节点的指针
}mempool;

/********************************************
*@brief 创建n个节点的内存池链表
*@param
*    num			数量
*    blocksize   内存块大小
*@return OPERA_OK/OPERA_ERR
*@see
*********************************************/
mempool *CreatePool(int num, int blocksize);

/********************************************
*@brief 销毁内存池
*@param
*    poolhead			内存池指针
*@return OPERA_OK/OPERA_ERR
*@see
*********************************************/
int  DestroyPool(mempool  *poolhead);

/********************************************
*@brief  得到一个内存块
*@param
*    poolhead			内存池指针
*@return 内存块地址
*@see
*********************************************/
char *GetMemblock(mempool *poolhead);

/********************************************
*@brief  释放一个内存块
*@param
*	 pmem				内存块地址
*    poolhead		内存池指针
*@return  OPERA_OK/OPERA_ERR
*@see
*********************************************/
int ReleaseMemblock(char* pmem, mempool *poolhead);


#endif
.c文件

#include "pool.h"

/********************************************
*@brief 创建n个节点的内存池链表
*@param
*    num			数量
*    blocksize   内存块大小
*@return OPERA_OK/OPERA_ERR
*@see
*********************************************/
 mempool *CreatePool(int num,int blocksize )
{
	if(num<=0||blocksize<=0)
	{
		printf("Create  input err\n");
		return NULL;
	}
	//内存池指针分配内存
	mempool *poolhead=NULL;		//内存池指针
	poolhead=(mempool*)malloc(sizeof(mempool));//池节点申请内存
	if (NULL==poolhead)
	{
		printf("poolhead malloc err!\n");
		return NULL;
	}
	memset(poolhead,0,sizeof(mempool));
	//内存池指针部分初始化赋值,其他默认为0无需初始
	poolhead->cnt=num;
	poolhead->blocksize=blocksize;
	//定义链表操作临时指针
	memblock *p1 = NULL;	//创建的新节点的地址
	memblock *p2 = NULL;	
	char* block;						//内存块指针
	int n = 0;							//创建前链表的节点总数为0:空链表
	//分配第一个内存块
	p1 = ( memblock *) malloc (LEN);	//开辟第一个新节点
	if (NULL == p1)
	{
		printf("p1 %d malloc err!\n",n+1);
		return NULL;
	}
	memset(p1,0,LEN);
	block=(char*)malloc(blocksize);//开辟内存块
	if (NULL == block)
	{
		printf("firstblock malloc err!\n");
		return NULL;
	}
	memset(block,0,blocksize);
	//*内存池,内存块初始化赋值
	p1->pmem=block;
	poolhead->firstaddr=block;
 	p2 = p1;			//如果节点开辟成功,则p2先把它的指针保存下来以备后用
	if(p1==NULL)		//节点开辟不成功
	{
		printf ("\nCann't create it, try it again in a moment!\n");
		return NULL;
	}
	while(n <num)		
	{
		n += 1;			//节点总数增加1个	
		if(n == 1)		//如果节点总数是1,则head指向刚创建的节点p1
		{
			poolhead->firstblock = p1;
			p2->next = NULL;  //此时的p2就是p1,也就是p1->next指向NULL。
		}
		else
		{
			p2->next = p1;	//指向上次下面刚刚开辟的新节点
		}
		p2 = p1;			//把p1的地址给p2保留,然后p1产生新的节点

		p1 = ( memblock *) malloc (LEN);//开辟出新节点
		if (NULL == p1)
		{
			printf("p1 %d malloc err!\n",n+1);
			return NULL;
		}
		memset(p1,0,LEN);
		block=(char*)malloc(blocksize);//开辟出新内存块
		if (NULL == block)
		{
			printf("block %d malloc err!\n", n + 1);
			return NULL;
		}
		memset(block,0,blocksize);
		p1->pmem=block;
	}
	p2->next = NULL;		//链表的最后一个节点指向NULL
	poolhead->lastaddr=p2->pmem+blocksize;//内存池 末尾地址

	free(p1->pmem);
	free(p1);			//跳出了while循环,释放p1   多余的那个空间
	p1 = NULL;			
	return poolhead;	    //返回创建链表的头指针 
}

 /********************************************
 *@brief 销毁内存池
 *@param
 *    poolhead			内存池指针
 *@return OPERA_OK/OPERA_ERR
 *@see
 *********************************************/
int  DestroyPool(mempool  *poolhead)  
{  
	if(poolhead==NULL)
	{
		return OPERA_ERR;
	}
	memblock  *p1=poolhead->firstblock;  
	memblock  *p2=p1;
    while(p1!=NULL)  
    {  
        p2=p1;  
		p1=p1->next;  
		free(p2->pmem);
		p2->pmem=NULL;
        free(p2);  
    }  
	poolhead->firstblock=NULL;	
	free(poolhead);
	poolhead = NULL;
	return OPERA_OK;  
} 

/********************************************
*@brief  得到一个内存块
*@param
*    poolhead			内存池指针
*@return 内存块地址
*@see
*********************************************/
char *GetMemblock(mempool *poolhead)
{
	if(poolhead->usedcnt==poolhead->cnt)
	{
		printf("GetMemblock ERR !Pool Full!\n");
		return NULL;
	}
	if (poolhead==NULL||poolhead->firstblock==NULL)
	{
		printf("pool in err!\n");
		return NULL;
	}
	memblock* p=poolhead->firstblock;
	poolhead->firstblock = p->next;
	p->next = NULL;
	poolhead->usedcnt++;
	return p->pmem;
}
/********************************************
*@brief  释放一个内存块
*@param
*	 pmem				内存块地址
*    poolhead			内存池指针
*@return  OPERA_OK/OPERA_ERR
*@see
*********************************************/
int ReleaseMemblock(char* pmem, mempool *poolhead)
{
	if(pmem==NULL)
	{
		printf("Realease Mem input ERR!\n");
		return OPERA_ERR;
	}
	memblock *ptemp = (memblock *)malloc(LEN);
	if (NULL == ptemp)
	{
		printf("ptemp malloc err!\n");
		return OPERA_ERR;
	}
	ptemp->pmem = pmem;
	ptemp->next=poolhead->firstblock;
	poolhead->firstblock = ptemp;
	poolhead->usedcnt--;
	return OPERA_OK;
}

测试实例

#include "pool.h"
int main()
{
	int ret = OPERA_OK;
	mempool *pool = NULL;
	pool = CreatePool(3, 1024);//建立内存池
	if (pool == NULL)
	{
		printf("Creat ERR!\n");
	}
	else
	{
		printf("Creat OK!\n");
	}
	printf("内存池信息 块数量%d,块大小%d,使用个数%d,起始地址0x%p,终止地址0x%p\n", pool->cnt, pool->blocksize, pool->usedcnt, pool->firstaddr, pool->lastaddr);
	char *Mem1 = GetMemblock(pool);
	printf("得到内存块地址0x%p\n", Mem1);
	printf("内存池信息 块数量%d,块大小%d,使用个数%d,起始地址0x%p,终止地址0x%p\n", pool->cnt, pool->blocksize, pool->usedcnt, pool->firstaddr, pool->lastaddr);
	char *Mem2 = GetMemblock(pool);
	printf("得到内存块地址0x%p\n", Mem2);
	printf("内存池信息 块数量%d,块大小%d,使用个数%d,起始地址0x%p,终止地址0x%p\n", pool->cnt, pool->blocksize, pool->usedcnt, pool->firstaddr, pool->lastaddr);
	char *Mem3 = GetMemblock(pool);
	printf("得到内存块地址0x%p\n", Mem3);
	printf("内存池信息 块数量%d,块大小%d,使用个数%d,起始地址0x%p,终止地址0x%p\n", pool->cnt, pool->blocksize, pool->usedcnt, pool->firstaddr, pool->lastaddr);
	char *Mem4 = GetMemblock(pool);
	printf("得到内存块地址0x%p\n", Mem4);
	printf("内存池信息 块数量%d,块大小%d,使用个数%d,起始地址0x%p,终止地址0x%p\n", pool->cnt, pool->blocksize, pool->usedcnt, pool->firstaddr, pool->lastaddr);


	ReleaseMemblock(Mem2, pool);
	printf("释放第二个内存块0x%p\n", Mem2);
	printf("内存池信息 块数量%d,块大小%d,使用个数%d,起始地址0x%p,终止地址0x%p\n", pool->cnt, pool->blocksize, pool->usedcnt, pool->firstaddr, pool->lastaddr);
	char *Mem5 = GetMemblock(pool);
	printf("得到内存块地址0x%p\n", Mem5);
	printf("内存池信息 块数量%d,块大小%d,使用个数%d,起始地址0x%p,终止地址0x%p\n", pool->cnt, pool->blocksize, pool->usedcnt, pool->firstaddr, pool->lastaddr);


	ret = DestroyPool(pool);//销毁内存池

	if (ret == OPERA_ERR)
	{
		printf("Destory ERR!\n");
	}
	else
	{
		printf("Destroy OK!\n");
	}
	system("pause");
	return 0;
}



  • 5
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值