内存记录模块,记录所有使用的内存,实时查看哪里出现了内存泄漏

本文介绍了一个内存管理模块,用于大型项目开发中实时监控内存使用情况,解决内存泄漏问题。通过自定义分配和释放函数,记录分配内存的大小、地址及文件位置,实现内存使用的跟踪与分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在大型项目开发时使用这个模块实时监控内存使用情况,解决出现内存泄漏时不容易定位的问题

文件: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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿木小呆呆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值