在大型项目开发时使用这个模块实时监控内存使用情况,解决出现内存泄漏时不容易定位的问题
文件:MemoryManage.h
#ifndef _MEMORYMANAGE_H_
#define _MEMORYMANAGE_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NODE_NUM (15)
#define FILE_NAME_STR (120)
#define HASH_KEY_STR (32)
#define LOG_PATH ("/mnt/mtd/log/ProtocolMem.log")
extern void* MemManage_Malloc(size_t p_pSize, const char *p_pFile, int p_nLine);
extern void MemManage_Free(void* p_pMemoryAdress);
#define MALLOC(size) MemManage_Malloc(size, __FILE__, __LINE__)
#define FREE(p) MemManage_Free(p)
typedef struct MemManage_Node_t
{
int m_nKey;
int m_nMemorySize; /*malloc的内存大小*/
void *m_pMemoryAddress;
char m_szFileName[FILE_NAME_STR]; /*那个文件哪一行进行的malloc*/
struct MemManage_Node_t *m_pObjNextNode; /*当发生碰撞时,向后存储*/
}MemManage_Node;
extern int MemoryManage_Start( );
#endif
文件: MemoryManage.cpp
#include <math.h>
#include "MemoryManage.h"
#include "Common.h"
#include <pthread.h>
static MemManage_Node *objAllHashNode[MAX_NODE_NUM];
pthread_mutex_t MutexLock = PTHREAD_MUTEX_INITIALIZER;
int MemManage_Init( )
{
Mutex_Lock(&MutexLock);
for(int i = 0; i < MAX_NODE_NUM; ++i)
{
objAllHashNode[i] = (MemManage_Node *)malloc(sizeof(MemManage_Node));
assert(objAllHashNode[i]);
memset(objAllHashNode[i], 0, sizeof(MemManage_Node));
}
Mutex_UnLock(&MutexLock);
return _SN_SUCCESS;
}
static int MemManage_UnInit( )
{
Mutex_Lock(&MutexLock);
for(int i = 0; i < MAX_NODE_NUM; ++i)
{
if(objAllHashNode[i] != NULL)
{
free(objAllHashNode[i]);
objAllHashNode[i] = NULL;
}
}
Mutex_UnLock(&MutexLock);
return _SN_SUCCESS;
}
int MemManage_Ch2Int(char p_cCh)
{
if((p_cCh >= '0') && (p_cCh <= '9'))
{
return p_cCh - '0';
}
else if((p_cCh >= 'A') && (p_cCh <= 'F'))
{
return p_cCh - 'A' + ('9' - '0' + 1);
}
return 0;
}
static unsigned int MemManage_Str2HashVal(const char* p_pStr)
{
unsigned char *pTempStr = (unsigned char*)p_pStr;
unsigned int nHash = 0;
float nSeed = 3;//3,5,7,9,...,etc奇数,系数取大于1的奇数,可以有效避免碰撞
float nIndex = 0;
float nLen = strlen((char*)pTempStr);
while( *pTempStr )
{
nHash = nHash + pow(nSeed,nLen-nIndex-1)*(*pTempStr);
++pTempStr;
nIndex++;
}
return nHash%MAX_NODE_NUM;
}
/*计算key值*/
static int MemManage_Get_Key(MemManage_Node *p_pObjNodeInfo)
{
if(!p_pObjNodeInfo)
{
Error_Printf("HashTable_Get_Key Failed, Hash_Node is Null !!!\n");
return _SN_ERROR;
}
char szStr[HASH_KEY_STR] = { 0 };
snprintf(szStr, HASH_KEY_STR, "%p", p_pObjNodeInfo->m_pMemoryAddress);
int nStrLen = strlen(szStr);
return MemManage_Str2HashVal(szStr);
}
/*插入*/
int MemManage_Insert(MemManage_Node *p_pObjNodeInfo)
{
if(!p_pObjNodeInfo)
{
Error_Printf("MemManage_Insert Failed, Hash_Node is Null !!!\n");
return _SN_ERROR;
}
MemManage_Node *objNode = NULL;
MemManage_Node *objNewNode = NULL;
int nKey = MemManage_Get_Key(p_pObjNodeInfo);
if(nKey <= _SN_ERROR)
{
Error_Printf("MemManage_Insert Err !!\n");
return _SN_ERROR;
}
Mutex_Lock(&MutexLock);
if(nKey <= MAX_NODE_NUM)
{
objNode = objAllHashNode[nKey];
if(!objNode)
{
Error_Printf("Hash Table Anomalous, objHashNode[nKey] is Null nKey = %d !!!\n", nKey);
Mutex_UnLock(&MutexLock);
return _SN_ERROR;
}
/*把数据放入链表尾部*/
{
/*找到链表尾部*/
while(objNode->m_pObjNextNode != NULL)
{
objNode = objNode->m_pObjNextNode;
}
/*申请空间接入到尾部*/
objNewNode = (MemManage_Node *)malloc(sizeof(MemManage_Node));
if(!objNewNode)
{
Error_Printf("%s %d :malloc objNewNode Failed !!!\n", __FILE__, __LINE__);
Mutex_UnLock(&MutexLock);
return _SN_ERROR;
}
memset(objNewNode, 0, sizeof(MemManage_Node));
objNewNode->m_pObjNextNode = NULL;
objNewNode->m_nKey = nKey;
objNewNode->m_nMemorySize = p_pObjNodeInfo->m_nMemorySize;
objNewNode->m_pMemoryAddress = p_pObjNodeInfo->m_pMemoryAddress;
memcpy(objNewNode->m_szFileName, p_pObjNodeInfo->m_szFileName, strlen(p_pObjNodeInfo->m_szFileName));
objNode->m_pObjNextNode = objNewNode;
}
//Debug_Printf("MemManage_Insert Success !!!\n");
}
else
{
Error_Printf("Invilad Key(%d)\n", nKey);
}
Mutex_UnLock(&MutexLock);
return _SN_SUCCESS;
}
/*删除*/
int MemManage_Delete(MemManage_Node *p_pObjNodeInfo)
{
MemManage_Node *objNode = NULL;
if(!p_pObjNodeInfo)
{
Error_Printf("HashTable_Delete Failed, Hash_Node is Null !!!\n");
return _SN_ERROR;
}
if(!p_pObjNodeInfo->m_pMemoryAddress)
{
Error_Printf("MemManage_Delete Failed, m_pMemoryAddress is Null !!!\n");
return _SN_ERROR;
}
int nKey = MemManage_Get_Key(p_pObjNodeInfo);
if(nKey <= _SN_ERROR)
{
Error_Printf("MemManage_Get_Key Err !!\n");
return _SN_ERROR;
}
objNode = objAllHashNode[nKey];
if(!objNode)
{
Error_Printf("Hash Table Anomalous, objHashNode[nKey] is Null nKey = %d !!!\n", nKey);
return _SN_ERROR;
}
Mutex_Lock(&MutexLock);
/*匹配节点*/
while(objNode->m_pObjNextNode != NULL)
{
if(objNode->m_pObjNextNode->m_pMemoryAddress == p_pObjNodeInfo->m_pMemoryAddress)
{
MemManage_Node *objTempNode = objNode->m_pObjNextNode->m_pObjNextNode;
/*删除匹配到的节点*/
free(objNode->m_pObjNextNode);
objNode->m_pObjNextNode = objTempNode;
break;
}
objNode = objNode->m_pObjNextNode;
}
Mutex_UnLock(&MutexLock);
return _SN_SUCCESS;
}
void* MemManage_Malloc(size_t p_pSize, const char *p_pFile, int p_nLine)
{
MemManage_Node objHashNode;
void* pMemory = malloc(p_pSize);
if(objAllHashNode[0] != NULL)
{
memset(&objHashNode, 0, sizeof(MemManage_Node));
objHashNode.m_nMemorySize = p_pSize;
objHashNode.m_pMemoryAddress = pMemory;
snprintf(objHashNode.m_szFileName, FILE_NAME_STR,"file:%s line:%d", p_pFile, p_nLine);
MemManage_Insert(&objHashNode);
}
return pMemory;
}
void MemManage_Free(void* p_pMemoryAdress)
{
MemManage_Node objHashNode;
if(!p_pMemoryAdress)
{
Error_Printf("Release a null pointer\n");
}
if(objAllHashNode[0] != NULL)
{
memset(&objHashNode, 0, sizeof(MemManage_Node));
objHashNode.m_pMemoryAddress = p_pMemoryAdress;
MemManage_Delete(&objHashNode);
}
return free(p_pMemoryAdress);
}
/*打印当前内存情况*/
void MemoryManage_Printf( )
{
Mutex_Lock(&MutexLock);
Debug_Printf("================MemoryManage_Printf=================\n");
MemManage_Node *objHashNode = NULL;
for(int i = 0; i < MAX_NODE_NUM; ++i)
{
objHashNode = objAllHashNode[i];
if(objHashNode)
{
while(objHashNode->m_pObjNextNode)
{
Debug_Printf("Key: %d\n", objHashNode->m_pObjNextNode->m_nKey);
Debug_Printf("size: %d\n", objHashNode->m_pObjNextNode->m_nMemorySize);
Debug_Printf("MemoryAddress: %p\n", objHashNode->m_pObjNextNode->m_pMemoryAddress);
Debug_Printf("file: %s\n", objHashNode->m_pObjNextNode->m_szFileName);
objHashNode = objHashNode->m_pObjNextNode;
}
}
}
Debug_Printf("=====================================\n");
Mutex_UnLock(&MutexLock);
}
void MemoryManage_Svae( )
{
FILE *fp = NULL;
char szStr[STR_LONG_LEN1] = { 0 };
char szTime[STR_LONG_LEN] = { 0 };
Create_Timestamp(szTime, STR_LONG_LEN);
fp = fopen(LOG_PATH, "w");
if(fp != NULL)
{
MemManage_Node *objHashNode = NULL;
Mutex_Lock(&MutexLock);
for(int i = 0; i < MAX_NODE_NUM; ++i)
{
objHashNode = objAllHashNode[i];
if(objHashNode)
{
while(objHashNode->m_pObjNextNode)
{
snprintf(szStr, STR_LONG_LEN, "time: %s\t%s\tsize: %d\tMemoryAddress: %0xp\tKey: %d\n",szTime,
objHashNode->m_pObjNextNode->m_szFileName,
objHashNode->m_pObjNextNode->m_nMemorySize,
objHashNode->m_pObjNextNode->m_pMemoryAddress,
objHashNode->m_pObjNextNode->m_nKey);
fwrite(szStr, 1, strlen(szStr), fp);
objHashNode = objHashNode->m_pObjNextNode;
}
}
}
fclose(fp);
fp = NULL;
Mutex_UnLock(&MutexLock);
}
return;
}
void * MemoryManage_Run(void *)
{
time_t nLastTime = 0;
time_t nCurTime = 0;
for( ; ; )
{
nCurTime = time(NULL);
/*每10分钟把内存情况输入到文件*/
if(abs(nCurTime - nLastTime) > 3*60)
{
MemoryManage_Svae( );
MemoryManage_Printf( );
nLastTime = nCurTime;
}
sleep(10);
}
ERR:
MemManage_UnInit( );
return NULL;
}
int MemoryManage_Start( )
{
pthread_t Pid;
static int nIsRuning = 0;
if (0 == nIsRuning)
{
int nRet = MemManage_Init();
if (nRet != _SN_SUCCESS)
{
Error_Printf("MemManage_Init Failed !!!\n");
return nRet;
}
nRet = pthread_create(&Pid, NULL, MemoryManage_Run, NULL);
if (nRet)
{
Error_Printf("\n============= MemoryManage_Start Failed ===================\n");
return nRet;
}
nIsRuning = 1;
Debug_Printf("\n============= MemoryManage_Start Success ===================\n");
}
return _SN_SUCCESS;
}