发现两篇内存池的博文,博文地址如下,写的很好,能避免内存碎片和内存泄露问题,比我这个玩具代码要好很多,大家可以看看:
http://www.cnblogs.com/bangerlee/archive/2011/08/31/2161421.html
http://blog.csdn.net/060/article/details/1326025
在我们做项目的时候,经常会分配了内存,然后却忘了释放,造成内存泄漏的问题。
以下代码可以实现在代码退出的时候自动释放之前申请但未释放的内存。
其原理是:用一个双向链表维护申请的内存块,申请内存则插入对应节点,释放则删除相应节点;当程序退出的时候,遍历双向链表,释放内存,清空双向链表。
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Node
{
struct Node *preNode;//前一个节点
struct Node *nextNode;//后一个节点
void **varAddr;//存储指针变量的地址
int size;
char freed;
};
struct Chain
{
struct Node *first;
struct Node *last;
int size;
};
void InitChain();
struct Node* InitNode(struct Node *pn);
int Push(struct Node *pn);
int RemoveChain(void **id);
int FreeChain();
void* MyMalloc(void **p,int size);
void* MyCalloc(void **p,int nsize,int usize);
void* MyRealloc(void **p,int size);
void MyFree(void **p);
static struct Chain chain;//定义一个链表的静态变量
/*初始化链表*/
void InitChain()
{
chain.first=NULL;
chain.last=NULL;
chain.size=0;
}
/*初始化一个链表上的节点*/
struct Node* InitNode(struct Node *pn)
{
pn=(struct Node *)malloc(sizeof(struct Node));
if(pn==NULL)
return NULL;
pn->preNode=NULL;
pn->nextNode=NULL;
pn->freed=0;
pn->varAddr=0;
pn->size=0;
return pn;
}
/*加入一个新的内存分配的节点*/
int Push(struct Node *pn)
{
struct Node *last=chain.last;
struct Node *first=chain.first;
if(first==NULL)
{
chain.first=pn;
chain.last=pn;
}
else
{
chain.last->nextNode=pn;
pn->preNode=chain.last;
chain.last=pn;
}
chain.size++;
return 1;
}
/*
从链表中移除一个节点
*/
int RemoveChain(void **id)
{
struct Node *first=chain.first;
struct Node *tp1=NULL,*tp2=NULL;
if(first==NULL)
return 0;
while(first)
{
if((long)first->varAddr==(long)id)
{
tp1=first->preNode;
tp2=first->nextNode;
if(tp1)
{
if(tp2)
{
tp1->nextNode=tp2;
tp2->preNode=tp1;
}
else
{
tp1->nextNode=NULL;
chain.last=tp1;
}
}
else
{
tp2->preNode=NULL;
chain.first=tp2;
}
free(first);
chain.size--;
break;
}
first=first->nextNode;
}
return 1;
}
/*清空链表*/
int FreeChain()
{
struct Node *first=chain.first;
struct Node *tp1=NULL;
while(first)
{
tp1=first->nextNode;
free((void *)*(first->varAddr));
free(first);
first=tp1;
}
chain.first=NULL;
chain.last=NULL;
chain.size=0;
return 1;
}
/*
自定义的malloc,calloc,realloc,free函数
void **p参数 是存储分配内存地址的变量的地址,根据这个地址与分配内存关联,进行管理
*/
void* MyMalloc(void **p,int size)
{
struct Node *pn=NULL;
(*p)=malloc(size);
if(p==NULL)
return NULL;
pn=InitNode(pn);
if(pn==NULL)
return NULL;
pn->varAddr=p;
pn->size=size;
Push(pn);
return (*p);
}
void* MyCalloc(void **p,int nsize,int usize)
{
struct Node *pn=NULL;
(*p)=calloc(nsize,usize);
if(p==NULL)
return NULL;
pn=InitNode(pn);
if(pn==NULL)
return NULL;
pn->varAddr=p;
pn->size=nsize*usize;
Push(pn);
return (*p);
}
void* MyRealloc(void **p,int size)
{
struct Node *pn=NULL;
(*p)=realloc((*p),size);
if(p==NULL)
return NULL;
pn=InitNode(pn);
if(pn==NULL)
return NULL;
pn->varAddr=p;
pn->size=size;
RemoveChain(p);
Push(pn);
return (*p);
}
void MyFree(void **p)
{
if((*p)==NULL)
return;
free((*p));//释放内存
RemoveChain(p);//把相关节点从链表移除
}
int main()
{
char *p=NULL;
char *p2=NULL;
int *p3=NULL;
InitChain();
p=(char *)MyCalloc((void **)&p,100,sizeof(char));
strcpy(p,"abcdefgh...");
p2=(char *)MyMalloc((void **)&p2,18*sizeof(char));
p3=(int *)MyMalloc((void **)&p3,10*sizeof(int));
p3=(int *)MyRealloc((void **)&p3,20*sizeof(int));
MyFree((void **)&p2);
FreeChain();
return 0;
}