此malloc/free实现增加空闲块添加功能:AddFreeMemBlock
#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)
{
if(NULL == pMemory || Size <= MEM_HDR_SIZE) {
FreeHeader = NULL;
return;
}
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 from the free list */
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;
if(NULL == pMem) return;
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);
}
}
}
}
void AddFreeMemBlock(void * pMem, int Size)
{
if(NULL == pMem || Size <= MEM_HDR_SIZE) {
return;
}
((MemMgr_t *)pMem)->Size = Size - MEM_HDR_SIZE;
_free((char *)pMem + MEM_HDR_SIZE);
}
static int OutputFreeList(void)
{
int Count = 0;
int TotalSize = 0;
MemMgr_t *p = FreeHeader;
while(p != NULL) {
Count++;
TotalSize += p->Size;
printf("%08X(% 5d)->", p, p->Size);
if(Count % 30 == 0) {
printf("\n");
}
p = p->pNext;
}
printf("\nFreeListLength:%d(%d).\n", Count, TotalSize);
return Count;
}
#define MAX_ALLOC_SIZE 1024
#define TEST_MEM_ARRAY_SIZE 1000
#define FREE_MEM_SIZE (MAX_ALLOC_SIZE * 600) //TEST_MEM_ARRAY_SIZE)
typedef void * void_p_t;
int main(int argc, char* argv[])
{
void_p_t pMem[TEST_MEM_ARRAY_SIZE];
void_p_t pAddMem[10];
int i;
int AddMemIdx;
int RunTimes = 1000000;
if(argc > 1) {
sscanf(argv[1], "%i", &RunTimes);
}
for(i = 0; i < TEST_MEM_ARRAY_SIZE; i++) {
pMem[i] = NULL;
}
for(i = 0; i < sizeof(pAddMem)/sizeof(pAddMem[0]); i++) {
pAddMem[i] = NULL;
}
InitMemMgr(NULL, 0);
i = 0;
AddMemIdx = 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("%dth alloc:%d, Out of memory.\n", i, MemSize);
pAddMem[AddMemIdx] = malloc(FREE_MEM_SIZE);
printf("AddFreeMemBlockAddress:%08X(%d)\n", pAddMem[AddMemIdx], (int)FREE_MEM_SIZE);
AddFreeMemBlock(pAddMem[AddMemIdx], FREE_MEM_SIZE);
AddMemIdx++;
continue;
}
memset(pMem[MemLoc], 0x00, MemSize);
//printf("%08X(% 5d)% 8d\n", pMem[MemLoc], MemSize, i);
i++;
}
OutputFreeList();
for(i = 0; i < TEST_MEM_ARRAY_SIZE; i++) {
if(pMem[i] != NULL) {
_free(pMem[i]);
}
}
OutputFreeList();
for(i = 0; i < sizeof(pAddMem)/sizeof(pAddMem[0]); i++) {
if(NULL != pAddMem[i]) {
free(pAddMem[i]);
}
}
return 0;
}