在AMPS中,使用内存池来管理内存,具体机制见之前的文章《AMPS:内存管理(二)》,在代码中,使用了两种实现方式,第一种是数组+单链表。今天先看看这个方式下的内存池实现。
AMPS_MemoryMgt.h
#ifndef __HEADER_AMPS_MEMORY_MGMT_H__
#define __HEADER_AMPS_MEMORY_MGMT_H__
#include "AMPS_Defines.h"
#include "AMPS_Trace.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef void*(*AMPS_InternalMallocCallback)(int r_unSize);
typedef void*(*AMPS_InternalReallocCallback)(void* r_pvData, int r_unSize);
typedef void(*AMPS_InternalFreeCallback)(void* r_pvData);
// we need at least these many buffers
// _
// 1- 8 bytes |
// 2- 16 bytes |
// 3- 32 bytes > Lower limit chunks
// 4- 64 bytes |
// 5- 128 bytes |
// _
// _
// 6- 8 Kbytes |
// 7- 16 Kbytes > upper limit chunks
// 8- 32 Kbytes |
// 9- 64 Kbytes |
// _
#define MAX_SIZE 65536 + 1
#define LN_2 .6931471805599453 //val = log(x)/log(2)
#define LN2_OF_1024 10
#define NO_OF_SMALL_MEM_POOLS 32 //1024/32
#define NO_OF_LARGE_MEM_POOLS 10
#define NO_OF_BLOCKS_OF_SMALL_MEM_POOL 1000
#define MINIMUM_SMALL_MEM_BLOCK_SIZE 32
#define NO_OF_BLOCKS_OF_LARGE_MEM_POOL 500
#define MINIMUM_LARGE_MEM_BLOCK_SIZE 2048
#define OFFSET 21 // LN2_OF_1024 + 1024/32 -1
typedef struct _node t_node;
typedef struct _MemoryPool t_MemoryPool;
typedef struct _MemContext t_MemContext;
//requested size lies in the lower range of allocated buffers
#define GET_MEM_BUFFER_INDEX(size) (size <= 1024 ? (size -1)/32 : (int)(ceil((float)(log(size)/LN_2))) + OFFSET)
#define GET_INDEX_FROM_BUFFER(dataPtr) (*((int*)(dataPtr - sizeof(int))) < NO_OF_SMALL_MEM_POOLS+NO_OF_LARGE_MEM_POOLS ? *((int*)(dataPtr - sizeof(int))) : AMPS_ERROR_FAILURE)
/*链表结点结构*/
struct _node
{
t_node* poAMPSSListNext;
t_node* poAMPSSListPrev;
};
/*池中链表结构*/
struct _MemoryPool
{
t_node* poHead;
unsigned char* puchBuffer;
unsigned int nSize;
t_MemoryPool* poMemoryPoolNext;
};
/*内存池结构*/
struct _MemContext
{
AMPS_InternalMallocCallback pfAMPS_InternalMallocCallback;
AMPS_InternalReallocCallback pfAMPS_InternalReallocCallback;
AMPS_InternalFreeCallback pfAMPS_InternalFreeCallback;
int nNoOfMallocWithoutFree;
int nNoOfMallocWithoutFree2;
AMPS_BOOL bMMEnable;
t_MemoryPool poMemoryPools[NO_OF_SMALL_MEM_POOLS+NO_OF_LARGE_MEM_POOLS];
int nMallocCounts[NO_OF_SMALL_MEM_POOLS+NO_OF_LARGE_MEM_POOLS];
};
void* MM_Init(int r_bMMEnable);
void MM_Cleanup(void);
void MM_BufferInit(t_MemoryPool* r_poMemoryPools, int r_nBufferIndex, int r_nSize, int r_nChunks);
void MM_BufferDestroy(t_MemoryPool* r_poMemoryPools);
void* AMPS_InternalMalloc(int r_nSize);
void* AMPS_InternalRealloc(void* r_pvData, int r_nSize);
void AMPS_InternalFree(void* r_pvData);
void* OS_Malloc(int r_nSize);
void* OS_Realloc(void* r_pvData, int r_nSize);
void OS_Free(void* r_pvData);
void* MM_Malloc(int r_nSize);
void* MM_Realloc(void* r_pvData, int r_unSize);
void MM_Free(void* r_pvData);
void MM_BufferNew(int r_nSize);
int MM_GetNoOfChunks(int r_nSize);
void MM_BufferShow(t_MemoryPool* r_poMemoryPools, int r_nSize);
void MM_BufferDump(unsigned char* r_puchBuff, int r_nSize);
void MM_CalculateAndDisplayMemoryStats (void);
#ifdef __cplusplus
}
#endif
#endif /* __HEADER_AMPS_MEMORY_MGMT_H__ */
AMPS_MemoryMgt.c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "AMPS_LinkList.h"
#include "AMPS_Core.h"
#include "AMPS_Defines.h"
#include "AMPS_MemMgt.h"
t_MemContext* g_poMemContext;
int g_nTotalMallocs = 0;
int g_nTotalFrees = 0;
/*****************************************************************
函数名称: AMPS_InternalMalloc
功能描述: 内部的内存分配函数
入参::
int r_unSize 待分配的字节数
出参:
返回值:
void* 分配完成后的内存块指针
*****************************************************************/
void* AMPS_InternalMalloc(int r_unSize)
{
/*g_poMemContext->nNoOfMallocWithoutFree++;
if(g_poMemContext->nNoOfMallocWithoutFree > 17600)
{
printf("AMPS_InternalMalloc: ======================= App Memory Count %d\n", g_poMemContext->nNoOfMallocWithoutFree);
}*/
//return(g_poMemContext->pfAMPS_InternalMallocCallback(r_unSize));
void* pvReturnValue = NULL;
pvReturnValue = malloc(r_unSize);
if(NULL == pvReturnValue)
{
printf("OS_Malloc: malloc failed for size %d.\n", r_unSize);
return NULL;
}
memset(pvReturnValue, 0, r_unSize);
return pvReturnValue;
}
/*****************************************************************
函数名称: AMPS_InternalRealloc
功能描述: 重新分配内存
入参::
void* r_pvData 待重新分配的内存块
int r_unSize 需要增加的字节数
出参:
返回值:
void* 分配完成后的内存块指针
*****************************************************************/
void* AMPS_InternalRealloc(void* r_pvData, int r_unSize)
{
//return(g_poMemContext->pfAMPS_InternalReallocCallback(r_pvData, r_unSize));
void* pvReturnValue = NULL;
pvReturnValue = realloc(r_pvData, r_unSize);
if(NULL == pvReturnValue)
{
printf("OS_Realloc: realloc failed for size %d.\n", r_unSize);
return NULL;
}
return pvReturnValue;
}
/*****************************************************************
函数名称: AMPS_InternalFree
功能描述: 内存释放
入参::
void* r_pvData 待释放内存地址
出参:
返回值:
void
*****************************************************************/
void AMPS_InternalFree(void* r_pvData)
{
/*g_poMemContext->nNoOfMallocWithoutFree--;
if(g_poMemContext->nNoOfMallocWithoutFree < 17600)
{
printf("AMPS_InternalFree: =+=+=+=+=+=+=+=+=+=+=+=+= App Memory Count %d\n", g_poMemContext->nNoOfMallocWithoutFree);
}*/
//g_poMemContext->pfAMPS_InternalFreeCallback(r_pvData);
free(r_pvData);
r_pvData = NULL;
}
/*****************************************************************
函数名称: OS_Malloc
功能描述: 操作系统提供的内存分配
入参::
int r_unSize
出参:
返回值:
void
*****************************************************************/
void* OS_Malloc(int r_unSize)
{
void* pvReturnValue = NULL;
pvReturnValue = malloc(r_unSize);
if(NULL == pvReturnValue)
{
printf("OS_Malloc: malloc failed for size %d.\n", r_unSize);
return NULL;
}
memset(pvReturnValue, 0, r_unSize);
//g_nTotalMallocs++;
//printf("total mallocs=%d.\n", g_nTotalMallocs);
return pvReturnValue;
}
/*****************************************************************
函数名称: OS_Realloc
功能描述: 操作系统提供的内存重新分配
入参:
void* r_pvData
int r_unSize
出参:
返回值:
void
*****************************************************************/
void* OS_Realloc(void* r_pvData, int r_unSize)
{
void* pvReturnValue = NULL;
pvReturnValue = realloc(r_pvData, r_unSize);
if(NULL == pvReturnValue)
{
printf("OS_Realloc: realloc failed for size %d.\n", r_unSize);
return NULL;
}
return pvReturnValue;
}
/*****************************************************************
函数名称: OS_Free
功能描述: 操作系统提供的内存释放
入参:
void* r_pvData
出参:
返回值:
void
*****************************************************************/
void OS_Free(void* r_pvData)
{
/*if(NULL == r_pvData)
{
printf("OS_Free: NULL pointer.\n");
return;
}*/
free(r_pvData);
//g_nTotalMallocs--;
//printf("total frees=%d.\n", g_nTotalMallocs);
r_pvData = NULL;
}
//inialize all the blocks here..
//array of structures of different sized chunks
//|0| = |2k|-|2k|-|2k|...
//|1| = |4k|-|4k|-|4k|...
//|2| = |6k|-|6k|-|6k|...
/*****************************************************************
函数名称: MM_Init
功能描述: 内存管理模块初始化
入参:
int r_bMMEnable 是否使用内存池
出参:
返回值:
void*
*****************************************************************/
void* MM_Init(int r_bMMEnable)
{
int i,j =0;
int nLargeMemSize = 0;
/*内存模块指针*/
g_poMemContext = malloc(sizeof(t_MemContext));
if(NULL == g_poMemContext)
{
printf("MM_Init: malloc is failed for g_poMemContext.\n");
return NULL;
}
g_poMemContext->nNoOfMallocWithoutFree = 0;
g_poMemContext->bMMEnable = (AMPS_BOOL)r_bMMEnable;
/*是否使用内存池管理内存*/
if(AMPS_TRUE == r_bMMEnable)
{
/*初始化小块内存池,池中有42个链表(32个小块内存链表+10个大块内存链表)
这些链表有32k,64k,96K....的内存,链表的每一个结点,分别是32B, 64B....
同一个链表中各结点大小一样,结点中间都会有一个32位整形的索引值,比如第
一个链表的结构如下:
|0|32B|0|32B|0|32B|......*/
for(i=0, j=1; i<NO_OF_SMALL_MEM_POOLS; i++,j++) //low limit elements
{
printf("Initializing buffer with size = %d at index = %d \n", nLargeMemSize, i);
MM_BufferInit(&g_poMemContext->poMemoryPools[i], i, j*MINIMUM_SMALL_MEM_BLOCK_SIZE, NO_OF_BLOCKS_OF_SMALL_MEM_POOL);
}
/*初始化大内存块,原理与小内存块初始化一样*/
nLargeMemSize = MINIMUM_LARGE_MEM_BLOCK_SIZE;
for(i=0,j=1; i<NO_OF_LARGE_MEM_POOLS; i++,j++)
{
printf("Initializing buffer with size = %d at index = %d \n", nLargeMemSize, NO_OF_SMALL_MEM_POOLS+i);
MM_BufferInit(&g_poMemContext->poMemoryPools[NO_OF_SMALL_MEM_POOLS+i], NO_OF_SMALL_MEM_POOLS+i, nLargeMemSize, NO_OF_BLOCKS_OF_LARGE_MEM_POOL);
nLargeMemSize = nLargeMemSize*2;
}
/*内存操作函数*/
g_poMemContext->pfAMPS_InternalMallocCallback = MM_Malloc;
g_poMemContext->pfAMPS_InternalReallocCallback = MM_Realloc;
g_poMemContext->pfAMPS_InternalFreeCallback = MM_Free;
}
else
{
/*不使用内存池,直接使用操作系统提供的内存分配函数*/
g_poMemContext->pfAMPS_InternalMallocCallback = OS_Malloc;
g_poMemContext->pfAMPS_InternalReallocCallback = OS_Realloc;
g_poMemContext->pfAMPS_InternalFreeCallback = OS_Free;
}
/* j = i;
MM_BufferInit(&g_poMemContext->poMemoryPools[j], j, 262144, NO_OF_BLOCKS_OF_LARGE_MEM_POOL);*/
return g_poMemContext;
}
/*****************************************************************
函数名称: MM_Cleanup
功能描述: 内存管理模块销毁
入参:
int r_bMMEnable
出参:
返回值:
void*
*****************************************************************/
void MM_Cleanup(void)
{
t_MemContext* poMemContext = g_poMemContext;
t_MemoryPool* poNextMemoryPool = NULL;
t_MemoryPool* poPrevMemoryPool = NULL;
int i =0;
if(AMPS_TRUE == g_poMemContext->bMMEnable)
{
if(NULL != poMemContext)
{
/*逐一释放内存池中各链表结点内存*/
for(i=0; i<NO_OF_SMALL_MEM_POOLS+NO_OF_LARGE_MEM_POOLS; i++)
{
free(poMemContext->poMemoryPools[i].puchBuffer);
poNextMemoryPool = poMemContext->poMemoryPools[i].poMemoryPoolNext;
while(NULL != poNextMemoryPool)
{
poPrevMemoryPool = poNextMemoryPool;
poNextMemoryPool = poNextMemoryPool->poMemoryPoolNext;
MM_BufferDestroy(poPrevMemoryPool);
free(poPrevMemoryPool);
}
}
}
}
/*释放内存池指针所占内存*/
free(poMemContext);
}
/*****************************************************************
函数名称: MM_Malloc
功能描述: 内存管理模块内存分配
入参:
int r_nSize
出参:
返回值:
void*
*****************************************************************/
void* MM_Malloc(int r_nSize)
{
t_MemContext* poMemContext = g_poMemContext;
t_MemoryPool* poMemoryPool = NULL;
t_node* poNode = NULL;
/*根据大小获取一个偏移量,用于在内存池中查找对应的内存链表*/
int index = GET_MEM_BUFFER_INDEX(r_nSize);
if(AMPS_ERROR_FAILURE == index)
{
printf("AMPS_InternalMalloc: Invalid size arguement given %d \n", r_nSize);
return NULL;
}
/*分配的内存块总数目加1*/
poMemContext->nMallocCounts[index]++;
/*指向找到的内存链表*/
poMemoryPool = &poMemContext->poMemoryPools[index];
/*从链表头获取一个节点*/
poNode = poMemoryPool->poHead;
poMemoryPool->poHead = poMemoryPool->poHead->poAMPSSListNext;
if(NULL != poMemoryPool->poHead)
{
poMemoryPool->poHead->poAMPSSListPrev = NULL;
}
else
{
/*如果链表中无可用内存,重新分配*/
MM_BufferNew(poMemoryPool->nSize);
}
memset((void*)poNode, 0, r_nSize);
return poNode;
}
/*****************************************************************
函数名称: MM_Realloc
功能描述: 内存管理模块重新内存分配
入参:
void* r_pvData 原内存指针
int r_unSize 大小
出参:
返回值:
void*
*****************************************************************/
void* MM_Realloc(void* r_pvData, int r_unSize)
{
unsigned char* newptr = NULL;
int oldBuffSize = -1;
int index = 0;
t_MemContext* poMemContext = g_poMemContext;
unsigned char* puchData = (unsigned char*)r_pvData;
if(NULL == puchData)
{
return NULL;
}
/*计算当前所在内存指针在池中的链表索引*/
index = GET_INDEX_FROM_BUFFER(puchData);
if(AMPS_ERROR_FAILURE == index)
{
printf("AMPS_InternalRealloc: Invalid pvData pointer given for realloc \n");
return NULL;
}
oldBuffSize = poMemContext->poMemoryPools[index].nSize;
newptr = AMPS_InternalMalloc(r_unSize);
if(NULL == newptr)
{
printf("AMPS_InternalRealloc: Unable to allocate new memory for requested size = %d \n", r_unSize);
return NULL;
}
memcpy(newptr, puchData, oldBuffSize);
AMPS_InternalFree(puchData);
return newptr;
}
/*****************************************************************
函数名称: MM_Free
功能描述: 内存管理模块内存释放
入参:
void* r_pvData
出参:
返回值:
void
*****************************************************************/
void MM_Free(void* r_pvData)
{
t_MemContext* poMemContext = g_poMemContext;
unsigned char* puchData = (unsigned char*)r_pvData;
t_MemoryPool* poMemoryPool = NULL;
t_node* poNode = NULL;
int index = 0;
if (NULL == r_pvData)
{
return;
}
/*获取池中链表索引*/
index = GET_INDEX_FROM_BUFFER(puchData);
if(AMPS_ERROR_FAILURE == index)
{
printf("AMPS_InternalFree: Invalid pvData pointer given for free \n");
return ;
}
//poMemContext->nMallocCounts[index]--;
/*从链表头删除此结点*/
poMemoryPool = &poMemContext->poMemoryPools[index];
poNode = (t_node*)puchData;
poNode->poAMPSSListPrev = NULL;
poNode->poAMPSSListNext = poMemoryPool->poHead;
if(NULL != poMemoryPool->poHead) //there was no node left in the current buffer so poAMPSSListHead was NULL
{
poMemoryPool->poHead->poAMPSSListPrev = poNode;
}
poMemoryPool->poHead = poNode;
}
/*****************************************************************
函数名称: MM_BufferInit
功能描述: 内存链表头结点
入参:
t_MemoryPool* r_poMemoryPool 内存池中结点指针
int indexOfBuff 此结点在内存池中的位置
int size 待分配的各结点内存大小
int chunks 结点个数
出参:
返回值:
void*
*****************************************************************/
// Mark this buffer for use..
//1- initialize the poAMPSSListHead.
//2- write the chunk array index into it.
void MM_BufferInit(t_MemoryPool* r_poMemoryPool, int indexOfBuff, int size, int chunks)
{
t_MemoryPool* poMemoryPool = r_poMemoryPool;
t_node* prev_node = NULL;
t_node* node = NULL;
unsigned int* indexTag = 0;
int i=0;
/*以下假设indexOfbuff=0,size=32,chunks=1000进行讲解*/
/*分配所表示链表占用的总内存*/
poMemoryPool->puchBuffer = malloc(size*chunks + chunks*sizeof(int));
/*链表结点个数*/
poMemoryPool->nSize = size;
/*下一个结点置NULL*/
poMemoryPool->poMemoryPoolNext = NULL;
/*内存前4个字节置为当前总链表数组偏移量*/
indexTag = (unsigned int*)&poMemoryPool->puchBuffer[0];
*indexTag = indexOfBuff;
/*第二个结点从内存块的第4个字节开始,因为前四个字已经存放了下标*/
node = (t_node*)&poMemoryPool->puchBuffer[sizeof(int)];
node->poAMPSSListPrev = NULL;
node->poAMPSSListNext = NULL;
/*链表头指针这个结点*/
poMemoryPool->poHead = node;
prev_node = node;
for(i=1; i< chunks; i++)
{
int index = 0;
/*跳过前四个结点,中间再相隔32个字节*/
indexTag = (unsigned int*)&poMemoryPool->puchBuffer[i*size + i* sizeof(int)];
*indexTag = indexOfBuff;
/*再计算下一个节点的位置,最终形成了一个这样的链表:
每个结点前4个字节值一样,存放当前链表在整个池中的便宜量,
然后接着是32个字节。再下来就是下一个节点,其有1000个这样的结点*/
index = i*size + ((i*sizeof(int))+sizeof(int));
node = (t_node*)&poMemoryPool->puchBuffer[index];
prev_node->poAMPSSListNext = node;
node->poAMPSSListPrev = prev_node;
node->poAMPSSListNext = NULL;
prev_node = node;
}
}
/*****************************************************************
函数名称: MM_BufferDestroy
功能描述: 内存链表结点销毁
入参:
t_MemoryPool* r_poMemoryPool 内存池中结点指针
出参:
返回值:
void
*****************************************************************/
void MM_BufferDestroy(t_MemoryPool* r_poMemoryPool)
{
if(NULL != r_poMemoryPool->puchBuffer)
{
free(r_poMemoryPool->puchBuffer);
}
r_poMemoryPool->poHead = NULL;
r_poMemoryPool->puchBuffer = NULL;
}
/*****************************************************************
函数名称: MM_BufferNew
功能描述: 新分配一个内存链表
入参:
tr_nSize 大小
出参:
返回值:
void
*****************************************************************/
void MM_BufferNew(int r_nSize)
{
int chunks = 0;
t_MemoryPool* poNextMemoryPool = NULL;
t_MemoryPool* poNewMemBuff = NULL;
t_MemContext* poMemContext = (t_MemContext*)g_poMemContext;
/*获取池中链表索引*/
int index = GET_MEM_BUFFER_INDEX(r_nSize);
if(AMPS_ERROR_FAILURE == index)
{
printf("MM_BufferNew: Unable to get new buffer \n");
return ;
}
/*计算需要的块个数*/
chunks = MM_GetNoOfChunks(r_nSize)/2;
poNewMemBuff = malloc(sizeof(t_MemoryPool));
if(NULL == poNewMemBuff)
{
printf("MM_BufferNew: Unable to malloc for new buffer \n");
return ;
}
/*建立一个新的内存链表*/
MM_BufferInit(poNewMemBuff, index, r_nSize, chunks);
/*把新分配的链表挂在内存池上*/
//go to last node to add a new node
poNextMemoryPool = &poMemContext->poMemoryPools[index];
while(NULL != poNextMemoryPool->poMemoryPoolNext)
{
poNextMemoryPool = poNextMemoryPool->poMemoryPoolNext;
}
poNextMemoryPool->poMemoryPoolNext = poNewMemBuff;
poMemContext->poMemoryPools[index].poHead = poNewMemBuff->poHead;
}
/*****************************************************************
函数名称: MM_GetNoOfChunks
功能描述: 根据大小,计算所需要的内存块个数(一个块的大小为32B)
入参:
tr_nSize 大小
出参:
返回值:
int
*****************************************************************/
int MM_GetNoOfChunks(int bufferSize)
{
if(bufferSize < 1024)
{
int sizeIndex = (bufferSize-1)/32;
switch(sizeIndex)
{
case 0:
return 100;
break;
case 1:
return 125;
break;
case 2:
return 100;
break;
case 3:
return 100;
break;
case 4:
return 100;
break;
default :
return 28;
}
}
else
{
return 100;
}
}
/*****************************************************************
函数名称: MM_BufferShow
功能描述: 遍历内存链表
入参:
t_MemoryPool* r_poMemoryPool
tr_nSize 大小
出参:
返回值:
int
*****************************************************************/
//simply debug utility function to see if link list has been created correctly
void MM_BufferShow(t_MemoryPool* r_poMemoryPool, int r_nSize)
{
t_MemoryPool* poMemoryPool = r_poMemoryPool;
t_node* poNode = NULL;
int i=0;
poNode = (t_node*)&poMemoryPool->poHead;
while(NULL != poNode->poAMPSSListNext)
{
poNode = poNode->poAMPSSListNext;
i++;
}
}
void MM_BufferDump(unsigned char* buff, int size)
{
int i=0;
for(i=0; i< size; i++)
{
//printf%.2x ,", buff[i]);
if(i%8 == 0 && i!=0)
{
//printf\n");
}
}
}
/*****************************************************************
函数名称: MM_CalculateAndDisplayMemoryStats
功能描述: 查看内存池使用情况(总大小,已分配大小)
入参:
void
出参:
返回值:
int
*****************************************************************/
void MM_CalculateAndDisplayMemoryStats (void)
{
int i =0,j=0;
int nLargeMemSize = MINIMUM_LARGE_MEM_BLOCK_SIZE;
int nTotalMemory = 0;
printf(" ====== Memory Usage Count for Small memory chunks.=====\n");
for(i=0,j=1; i< NO_OF_SMALL_MEM_POOLS; i++,j++)
{
if(0 != g_poMemContext->nMallocCounts[i])
{
nTotalMemory += ((g_poMemContext->nMallocCounts[i] * (j*32))/1024);
printf("Pool Size = %d No Of Mallocs = %d total = %d kilo bytes\n", j*32, g_poMemContext->nMallocCounts[i], ((g_poMemContext->nMallocCounts[i] * (j*32))/1024));
}
}
printf(" ====== Memory Usage Count for Large memory chunks.=====\n");
for(i=0,j=1; i< NO_OF_LARGE_MEM_POOLS; i++,j++)
{
if(i == 0)
{
nLargeMemSize = nLargeMemSize;
}
else
{
nLargeMemSize = nLargeMemSize * 2;
}
if(0 != g_poMemContext->nMallocCounts[NO_OF_SMALL_MEM_POOLS + i])
{
nTotalMemory += ((g_poMemContext->nMallocCounts[NO_OF_SMALL_MEM_POOLS+i] * (nLargeMemSize))/1024);
printf("Pool Size = %d No Of Mallocs = %d total = %d kilo bytes\n", nLargeMemSize, g_poMemContext->nMallocCounts[NO_OF_SMALL_MEM_POOLS+i], ((g_poMemContext->nMallocCounts[NO_OF_SMALL_MEM_POOLS+i] * (nLargeMemSize))/1024));
}
}
printf("Total Memory Consumed is = %d Megs.\n", nTotalMemory/1024);
}