/*****************************************************************************************
内存栈动态申请与释放
文件:bspmem.h
编者:张永辉 2013年7月30日
*****************************************************************************************/
#ifndef _BSP_H_
#define _BSP_H_
#include "\embed\source\lib\basetype.h"
//*********************************配置***************************************************
//***************************************函数声明*****************************************
int BspMemInit(void);
int BspMemFreeSize(void);
int BspMemUsedSize(void);
void *BspMemMalloc(u32 size);
void BspMemFree(void* ptr);
//****************************************************************************************
#endif
/*****************************************************************************************
内存分配
文件:bspmem.c
编者:张永辉
平台:vs2008
参考:程序员的自我修养。。
*****************************************************************************************/
#define _BSP_C_
#include<Windows.h>
#include<process.h> //_beginthread
#include "bsp.h"
#include "bspdbg.h"
//****************************************************************************************
void *MathMemSet(void *ptr,char c,unsigned int len)
{
void * start = ptr;
if (ptr == 0)
{
return (void*)0;
}
while(len--)
{
*(char*)ptr = (char)c;
ptr = (char*)ptr+1;
}
return start;
}
/*****************************************************************************************
内存定义
*****************************************************************************************/
//大小及空间
#define HEAP_ALL_SIZE 1024 //总大小
int memblockcnt = 0; //已经使用了的块数目
static u8 mem[HEAP_ALL_SIZE]; //静态的内存空间,或指针也可以
//用于描述一个内存块 占16个字节
typedef struct _heap_header
{
enum
{
BLOCK_FREE = 0XABABABAB, //此块未被使用标志
BLOCK_USED = 0XCDCDCDCD //此块已被使用标志
}type;
u32 size; //此块的大小,包括头部
struct _heap_header *next; //下一个块
struct _heap_header *prev; //上一个块
}heap_header;
#define ADDR_ADD(a,o) (((char*)(a)) + o) //地址+偏移
static heap_header* list_head = NULL; //头指针
#define HEADER_SIZE (sizeof(heap_header))
/*****************************************************************************************
内存分配与释放
*****************************************************************************************/
//初始化
int BspMemInit(void)
{
list_head = (heap_header*)mem;
list_head->size = HEAP_ALL_SIZE; //第一块空间,是最大的
list_head->type = BLOCK_FREE; //是空闲空间
list_head->next = NULL;
list_head->prev = NULL;
memblockcnt = 0;
return 0;
}
//分配
void *BspMemMalloc(u32 size)
{
heap_header *header = NULL;
if (size == 0)
{
return NULL;
}
//遍历查找空块
header = list_head;
while(header != NULL)
{
if(header->type == BLOCK_USED)
{
header = header->next;
continue;
}
//只有中间的块刚好够用
if((header->size >= size + HEADER_SIZE) && (header->size < size + HEADER_SIZE * 2))
{
header->type = BLOCK_USED;
memblockcnt++;
return ADDR_ADD(header,HEADER_SIZE);
}
//有足够空间,分割
if(header->size >= size + HEADER_SIZE*2)
{
//下一个块的头部
heap_header* next = (heap_header*)ADDR_ADD(header,size + HEADER_SIZE);
next->prev = header;
next->next = header->next; //不是NLL
next->type = BLOCK_FREE;
next->size = header->size - (size + HEADER_SIZE);
//改变本次块的头部
header->next = next;
header->size = size + HEADER_SIZE;
header->type = BLOCK_USED;
memblockcnt++;
return ADDR_ADD(header,HEADER_SIZE);
}
header = header->next;
}
return 0;
}
//释放空间
void BspMemFree(void* ptr)
{
//找到头部
heap_header* header = (heap_header*)ADDR_ADD(ptr, (0-HEADER_SIZE));
if(header->type != BLOCK_USED)
{
return;
}
header->type = BLOCK_FREE;
//前面的为空则合并
if (header->prev != NULL && header->prev->type == BLOCK_FREE)
{
header->prev->next = header->next;
if (header->next != NULL)
{
header->next->prev = header->prev;
}
header->prev->size += header->size;
header = header->prev;
memblockcnt--;
}
//后面的为空则合并
if((header->next != NULL)&&(header->next->type==BLOCK_FREE))
{
header->size += header->next->size;
if(header->next->next!= NULL)
{
header->next->next->prev = header;
header->next = header->next->next;
}
else
{
header->next = NULL;
}
memblockcnt--;
}
}
/*****************************************************************************************
内存辅助分析--用于调试
*****************************************************************************************/
//总空间大小 若 AllSize == FreeSize + UsedSize 则正常,否则可能内存泄露、访问越界了
int BspMemAllSize(void)
{
return HEAP_ALL_SIZE;
}
//空闲空间的大小
int BspMemFreeSize(void)
{
int allsize = 0;
heap_header *header = NULL;
header = list_head;
while(header != NULL)
{
if (header->type == BLOCK_FREE)
{
allsize += header->size;
}
header = header->next;
}
return allsize;
}
//使用的的空间大小
int BspMemUsedSize(void)
{
int allsize = 0;
heap_header *header = NULL;
header = list_head;
while(header != NULL)
{
if (header->type == BLOCK_USED)
{
allsize += header->size;
}
header = header->next;
}
return allsize;
}
//已经使用的了块数目
int BspMemUsedBlock(void)
{
return memblockcnt;
}
//显示内存分配情况
void BspMemDisp(void)
{
int i = 0;
int allsize = 0;
heap_header *header = NULL;
//遍历
header = list_head;
while(header != NULL)
{
DBG_S_U32("\nMEM num = :",i);
if (header->type == BLOCK_FREE)
{
DBG_S(" type = free");
}else
{
DBG_S(" type = used");
}
DBG_S_U32(" size=",header->size);
DBG_S_U32(" prev = :",(int)(header->prev) - (int)mem);
DBG_S_U32(" this = :",(int)header - (int)mem);
DBG_S_U32(" next = :",(int)(header->next) - (int)mem);
DBG_S_U32(" this addr = :",(int)header);
allsize += header->size;
i++;
header = header->next;
}
DBG_S_U32("\nall size == ",allsize);
DBG_S_U32("\nfree size == ",BspMemFreeSize());
DBG_S_U32("\nUsed size == ",BspMemUsedSize());
DBG_S("\n");
}
/*****************************************************************************************
测试函数
*****************************************************************************************/
void BspMemTest_(void)
{
char *pc0;
char *pc1;
char *pc2;
char *pc3;
char *pc4;
BspMemDisp();
pc0 = BspMemMalloc(8);
MathMemSet(pc0,0x11,8);
pc1 = BspMemMalloc(8);
MathMemSet(pc1,0x22,8);
pc2 = BspMemMalloc(8);
MathMemSet(pc2,0x33,8);
pc3 = BspMemMalloc(4);
MathMemSet(pc3,0x44,5);
pc4 = BspMemMalloc(4);
MathMemSet(pc4,0x55,4);
BspMemDisp();
BspMemFree(pc2);
BspMemDisp();
BspMemFree(pc0);
BspMemDisp();
BspMemFree(pc1);
BspMemDisp();
BspMemFree(pc3);
BspMemDisp();
BspMemFree(pc4);
BspMemDisp();
}
int main(void)
{
BspMemInit();
BspMemDisp();
BspMemTest_();
BspMemTest_();
}