采用双向链表,首次适配算法,为将来的优化提供支持:每次释放时从最近一次分配处的下一空闲块开始比较、查找。单任务版本,多任务下需要对分配和释放加锁。
#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <memory.h>
typedef struct tagMemMgr_t
{
struct tagMemMgr_t *pNext;
struct tagMemMgr_t *pPrev;
int Size;
} MemMgr_t;
#define MEM_HDR_SIZE sizeof(MemMgr_t)
static MemMgr_t *FreeHeader;
void InitMemMgr(void * pMemory, int Size)
{
FreeHeader= (MemMgr_t *)pMemory;
FreeHeader->pNext = NULL;
FreeHeader->pPrev = NULL;
FreeHeader->Size = Size - MEM_HDR_SIZE;
}
void *_malloc(int Size)
{
MemMgr_t *p;
int RemainingSize;
Size = (Size + 3)/4 * 4;
p = FreeHeader;
while(NULL != p) {
if (p->Size >= Size) {
break;
}
else {
p = p->pNext;
}
}
if (NULL == p) return NULL;
RemainingSize = p->Size - Size;
if(RemainingSize > MEM_HDR_SIZE) { /* split the free block into 2 free block */
MemMgr_t *q;
q = (MemMgr_t *)((char *)p + MEM_HDR_SIZE + Size);
q->Size = RemainingSize - MEM_HDR_SIZE;
q->pNext = p->pNext;
q->pPrev = p->pPrev;
if(p->pPrev == NULL) {
FreeHeader = q;
}
else {
p->pPrev->pNext = q;
}
if(p->pNext != NULL) {
p->pNext->pPrev = q;
}
p->Size = Size;
}
else {
/* delete p */
if(p->pPrev == NULL) {
FreeHeader = p->pNext;
}
else {
p->pPrev->pNext = p->pNext;
}
if(p->pNext != NULL) {
p->pNext->pPrev = p->pPrev;
}
}
return (char *)p + MEM_HDR_SIZE;
}
/* q merges to p */
static MemMgr_t * MemMerge(MemMgr_t *p, MemMgr_t *q)
{
if(q == NULL) {
return NULL;
}
if(((char *)p + MEM_HDR_SIZE + p->Size) == (char *)q) {
/* delete q */
p->pNext = q->pNext;
if(q->pNext != NULL) {
q->pNext->pPrev = p;
}
p->Size += MEM_HDR_SIZE + q->Size;
return p;
}
else {
return NULL;
}
}
void _free(void * pMem)
{
MemMgr_t *pToFree, *p, *q;
pToFree = (MemMgr_t *)((char *)pMem - MEM_HDR_SIZE);
if(FreeHeader == NULL) {
FreeHeader = pToFree;
FreeHeader->pNext = NULL;
FreeHeader->pPrev = NULL;
return;
}
q = FreeHeader;
p = q->pPrev;
while(q != NULL && pToFree > q) {
p = q;
q = q->pNext;
}
if(p == NULL) { /* pToFree should be the first free block */
pToFree->pNext = FreeHeader;
pToFree->pPrev = NULL;
FreeHeader->pPrev = pToFree;
FreeHeader = pToFree;
MemMerge(FreeHeader, FreeHeader->pNext);
}
else {
if(q == NULL) { /* pToFree as the last free block */
pToFree->pNext = NULL;
pToFree->pPrev = p;
p->pNext = pToFree;
MemMerge(p, pToFree);
}
else { /* pToFree insert into the free list */
pToFree->pNext = q;
pToFree->pPrev = p;
p->pNext = pToFree;
q->pPrev = pToFree;
if(NULL != MemMerge(p, pToFree)) {
MemMerge(p, q);
}
else {
MemMerge(pToFree, q);
}
}
}
}
static int OutputFreeList(void)
{
int Count = 0;
MemMgr_t *p = FreeHeader;
while(p != NULL) {
printf("%08X(% 5d)->", p, p->Size);
p = p->pNext;
Count++;
if(Count % 30 == 0) {
printf("\n");
}
}
printf("\nFreeListLength:%d\n", Count);
return Count;
}
#define MAX_ALLOC_SIZE 1024
#define TEST_MEM_ARRAY_SIZE 1000
#define FREE_MEM_SIZE (MAX_ALLOC_SIZE * TEST_MEM_ARRAY_SIZE)
typedef void * void_p_t;
int main(int argc, char* argv[])
{
void *p;
void_p_t pMem[TEST_MEM_ARRAY_SIZE];
int i;
int RunTimes = 1000000;
if(argc > 1) {
sscanf(argv[1], "%i", &RunTimes);
}
p = malloc(FREE_MEM_SIZE);
if(NULL == p) return -1;
printf("FreeMemoryStartAddress:%08X\n", p);
InitMemMgr(p, FREE_MEM_SIZE);
for(i = 0; i < TEST_MEM_ARRAY_SIZE; i++) {
pMem[i] = NULL;
}
i = 0;
srand((unsigned)time(NULL));
while(RunTimes--) {
int MemLoc;
int MemSize;
MemLoc = rand() % TEST_MEM_ARRAY_SIZE;
if(pMem[MemLoc] != NULL) {
_free(pMem[MemLoc]);
}
MemSize = rand() % MAX_ALLOC_SIZE;
pMem[MemLoc] = _malloc(MemSize);
if(NULL == pMem[MemLoc]) {
printf("Out of memory\n");
break;
}
memset(pMem[MemLoc], 0x00, MemSize);
printf("%08X(% 5d)% 8d\n", pMem[MemLoc], MemSize, i++);
}
OutputFreeList();
for(i = 0; i < TEST_MEM_ARRAY_SIZE; i++) {
if(pMem[i] != NULL) {
_free(pMem[i]);
}
}
OutputFreeList();
free(p);
return 0;
}