C++内存泄漏检测(调试工具)

理论

  • 什么是内存泄露:指因为疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并不是指内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误,失去了对该段内存的控制,因而造成了内存的浪费。

工具作用

  • 在使用Debug版的malloc分配内存时,malloc会在内存块的头中记录分配该内存的文件名及行号。
  • 当程序退出时会在main()函数返回之后做一些清理工作,这个时候来检查调试堆内存,如果仍然有内存没有被释放,则一定是存在内存泄漏。
  • 从没有被释放的内存块,就可以获得文件名、行号,泄漏多少字节,会打印显示出来。
  • 如下图所示,内存泄漏检测工具运行的效果。

C++内存泄漏检测(调试工具)

Debug调试常用的宏

__FILE__            //所在的文件
__FUNCTION__        //函数功能
__FUNCDNAME__       //函数名
__LINE__            //在第几行
__DATE__            //产生的日期
__TIME__            //产生的时间

代码实现

MemoryCheck.h

#pragma once
#ifndef __MEMORY_CHECK_H__
#define __MEMORY_CHECK_H__
#ifdef _DEBUG

void* operator new(size_t size, const char* filename, const char* funame, int line);
void* operator new[](size_t size, const char* filename, const char* funame, int line);
void operator delete(void* pMem);
void operator delete[](void* pMem);

#ifndef __USE_MEM_CHECK__
#define __USE_MEM_CHECK__
#define new new(__FILE__,__FUNCTION__,__LINE__)
#endif // !__USE_MEM_CHECK__
#endif // _DEBUG
#endif // !__MEMORY_CHECK_H__

MemoryCheck.cpp

#include<map>
#include<iostream>
#include<Windows.h>
#define __USE_MEM_CHECK__
#include"MemoryCheck.h"

typedef struct stMemInfo
{
	void* pMem;
	size_t size;
	int line;
	char funcname[256];
	char filename[256];
}MEMINFO,*LPMEMINFO;


std::map<void*, LPMEMINFO>g_MemMap;//存储内存分配的信息
typedef std::map<void*, LPMEMINFO>MEMMAP;
typedef MEMMAP::iterator MEMMAPItr;

class CMemMgr
{
public:
	static CMemMgr& Instance()
	{
		static CMemMgr instance;
		return instance;
	}

	void* Push(LPMEMINFO pInfo)
	{
		g_MemMap[pInfo->pMem] = pInfo;
		return pInfo->pMem;
	}
	void Pop(void* pMem)
	{
		MEMMAPItr it = g_MemMap.find(pMem);
		if (it != g_MemMap.end())
		{
			free(pMem);
			free(it->second);
			g_MemMap.erase(it);
		}
	}
	~CMemMgr()
	{
		if (!g_MemMap.empty())
		{
			OutputDebugStringA("n----------------------------------发现内存泄露信息----------------------------------nn");
			char buf[256] = {};
			int count = 0;
			for (auto it:g_MemMap)
			{
				sprintf_s(buf, "【内存泄漏警告 %d 】 文件%s,第%d行的函数%s中泄漏了%d个字节的内存n",
					count++,
					it.second->filename,
					it.second->line,
					it.second->funcname,
					it.second->size);

				OutputDebugStringA(buf);
				free(it.second->pMem);
				free(it.second);
			}
			g_MemMap.clear();
			OutputDebugStringA("n-------------------------------内存泄漏检测结束----------------------------------nn");
		}
	}
private:
	CMemMgr() {};
	CMemMgr& operator=(const CMemMgr&) = delete;
	CMemMgr(const CMemMgr&) = delete;
};


void* operator new(size_t size, const char* filename, const char* funcname, int line)
{
	LPMEMINFO pInfo=(LPMEMINFO)malloc(sizeof(MEMINFO));
	pInfo->size = size;
	pInfo->line = line;
	pInfo->pMem = malloc(size);
	strcpy_s(pInfo->filename, filename);
	strcpy_s(pInfo->funcname, funcname);
	return CMemMgr::Instance().Push(pInfo);
}
void* operator new[](size_t size, const char* filename, const char* funcname, int line)
{
	return operator new(size, filename, funcname, line);
}
void operator delete(void* pMem)
{
	CMemMgr::Instance().Pop(pMem);
}
void operator delete[](void* pMem)
{
	operator delete(pMem);
}

main.cpp

#include<iostream>
#include"MemoryCheck.h"

int main()
{
	int* p = new int;
	int* p2 = new int[5];
	system("pause");
	return 0;
}

注意

  • 重载的new相冲突解决办法:
  • 1.使用宏定义开关#define USE_MEM_CHECK,定义在MemoryCheckr.h的前面才能实现宏定义开关,注意顺序很重要,顺序错误也会导致不识别。
  • 2.使用#undef new也可解决

原文链接: https://www.cnblogs.com/biu-we/p/13360000.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    C++内存泄漏检测(调试工具)

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/200709

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月12日 下午8:31
下一篇 2023年2月12日 下午8:31

相关推荐