求:有什么工具可以很好的检测内存泄露呀?谢谢

gijquery4 2013-04-30 12:12:47
VC2008写的DLL,可以进行多线程调用。

请问用什么工具可以很好的检测内存是否泄露呀?谢谢
...全文
114 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
gijquery4 2013-05-05
  • 打赏
  • 举报
回复
求帮助哦。。。。。
满衣兄 2013-05-02
  • 打赏
  • 举报
回复
boundchecker
wumn29 2013-05-02
  • 打赏
  • 举报
回复
/************************************************************************
* 类名:CMemPool
* 功能:windows内存池。
		1、此内存池的目的主要是方便定位内存泄露
		2、调试开关打开的时候会将内存泄露的信息打印出来
		3、注意:此内存池只分配内存,不会调用构造函数,不适用于自定义
		数据类型(只针对char、int、short、double等基本数据类型)

* 作者:王威
* 时间:2013-03-12
* 版本:1.0.0.1
************************************************************************/
#pragma once

#include <fstream>
#include <list>
using namespace std;


template<typename T>
class CMemPool
{
private:
	struct SM
	{
		int size;						//申请的内存大小
		T* pt;							//申请的内存首地址
		unsigned char flg;				//0从未使用的内存, 1正在使用, 2回收的内存
	};

	CMemPool(const CMemPool&){};		//禁止拷贝构造
	list<SM> m_list;
	CRITICAL_SECTION m_csMemLock;

#ifdef _DEBUG
	CString m_csLogPath;
#endif

	CMemPool(int size = 1)
	{
		InitializeCriticalSection(&m_csMemLock);
		SM sm;
		for(int i = 0; i < size; ++i)
		{
			sm.size = 512;
			sm.pt = (T*)malloc(sizeof(T)*512); 
			sm.flg = 0;
			m_list.push_front(sm);
		}

#ifdef _DEBUG
		//获取日志文件目录
		char szPath[MAX_PATH] = {0};
		::GetModuleFileNameA(NULL, szPath, MAX_PATH);
		m_csLogPath = szPath;
		int pos = m_csLogPath.ReverseFind(_T('\\'));
		m_csLogPath = m_csLogPath.Left(pos+1);
		m_csLogPath += "MemPool.log";
		std::locale::global(std::locale(""));//使用STL函数设置为系统语言环境,解决bug:fstream不支持中文目录路径
		ofstream out2file(m_csLogPath, ios::out);
		out2file.close();
#endif
	};
	
public:
	static CMemPool<T>* Instance(int size = 20)
	{
		static CMemPool<T> ins(size);
		return &ins;
	};

	virtual ~CMemPool()
	{
		CheckMemeryLeak();
		DeleteCriticalSection(&m_csMemLock);
		list<SM>::iterator it;
		for(it = m_list.begin(); it != m_list.end(); ++it)
		{
			free(it->pt);
		}
		m_list.clear();
	};

	T* New(int size = 1, const char* file = "", const char* func = "", int line = 0)
	{
		EnterCriticalSection(&m_csMemLock);
#ifdef _DEBUG
		string filestr(file);
		string::size_type fid = filestr.rfind('\\');
		if (fid != string::npos)
		{
			filestr = filestr.substr(fid+1, filestr.length()-fid-1);
		}
		ofstream out2file(m_csLogPath, ios::app);
#endif
		if (m_list.size() < 1 || m_list.front().flg == 1) //池为空或者没有空闲的内存需要重新申请
		{
#ifdef _DEBUG
			if (out2file.is_open())
			{
				out2file<<filestr<<"("<<line<<") : "<<func<<"----New:池为空或者没有空闲的内存需要重新申请, size="<<size<<", m_list.size() = "<<m_list.size()+1<<"\n";
			}
#endif
			SM sm;
			sm.size = size;
			sm.pt = (T*)malloc(sizeof(T)*size);
			sm.flg = 0;
			m_list.push_front(sm);
		}
		SM tsm = m_list.front();
		if (tsm.size < size)	//改变大小
		{
			tsm.pt = (T*)realloc(tsm.pt, sizeof(T)*size);
#ifdef _DEBUG
			if (out2file.is_open())
			{
				CString addr;
				addr.Format("0x%p", tsm.pt);
				out2file<<filestr<<"("<<line<<") : "<<func<<"----New:改变大小 首地址="<<addr<<", from "<<tsm.size<<" to "<<size<<"\n";
			}
			out2file.close();
#endif
			tsm.size = size;
		}
		else
		{
#ifdef _DEBUG
			if (out2file.is_open())
			{
				CString addr;
				addr.Format("0x%p", tsm.pt);
				out2file<<filestr<<"("<<line<<") : "<<func<<"----New:从池中取出内存, 首地址="<<addr<<" , size= "<<tsm.size<<"\n";
			}
			out2file.close();
#endif
		}
		tsm.flg = 1;			//设置此节点内存不可分配
		m_list.pop_front();		//从头部删除
		m_list.push_back(tsm);	//插入到尾部
		LeaveCriticalSection(&m_csMemLock);
		return tsm.pt;
	};

	void Delete(void* pt, const char* file, const char* func, int line)
	{
		EnterCriticalSection(&m_csMemLock);
#ifdef _DEBUG
		string filestr(file);
		string::size_type fid = filestr.rfind('\\');
		if (fid != string::npos)
		{
			filestr = filestr.substr(fid+1, filestr.length()-fid-1);
		}
		ofstream out2file(m_csLogPath, ios::app);
#endif
		if (pt == 0)
		{
#ifdef _DEBUG
			if (out2file.is_open())
			{
				out2file<<filestr<<"("<<line<<") : "<<func<<"----Delete:传入了空指针"<<"\n";
			}
			out2file.close();
#endif
			LeaveCriticalSection(&m_csMemLock);
			return;
		}
		
		list<SM>::reverse_iterator rit;
		for (rit = m_list.rbegin(); rit != m_list.rend(); ++rit)
		{
			if (rit->pt == (T*)pt)//找到了要释放的内存
			{
				if(rit->flg == 0)
				{
#ifdef _DEBUG
					if (out2file.is_open())
					{
						CString addr;
						addr.Format("0x%p", pt);
						out2file<<filestr<<"("<<line<<") : "<<func<<"----Delete:找到了要释放的内存,但是改内存不是从池中New出来的, 首地址="<<addr<<"\n";
					}
					out2file.close();
#endif
					LeaveCriticalSection(&m_csMemLock);
					return;
				}
				else if(rit->flg == 2)
				{
#ifdef _DEBUG
					if (out2file.is_open())
					{
						CString addr;
						addr.Format("0x%p", pt);
						out2file<<filestr<<"("<<line<<") : "<<func<<"----Delete:找到了要释放的内存,但是该内存是池中已经释放的, 首地址="<<addr<<"\n";
					}
					out2file.close();
#endif
					LeaveCriticalSection(&m_csMemLock);
					return;
				}
				SM tsm;
				tsm.flg = 2;
				tsm.pt = rit->pt;
				tsm.size = rit->size;
				m_list.erase(--rit.base());
				m_list.push_front(tsm);
#ifdef _DEBUG
				if (out2file.is_open())
				{
					CString addr;
					addr.Format("0x%p", pt);
					out2file<<filestr<<"("<<line<<") : "<<func<<"----Delete:成功释放内存, 首地址="<<addr<<"\n";
				}
				out2file.close();
#endif
				LeaveCriticalSection(&m_csMemLock);
				return;
			}
		}
#ifdef _DEBUG
		if (out2file.is_open())
		{
			out2file<<filestr<<"("<<line<<") : "<<func<<"----Delete:没有找到要释放的内存"<<"\n";
		}
		out2file.close();
#endif
		LeaveCriticalSection(&m_csMemLock);
	};
	
	void CheckMemeryLeak()
	{
#ifdef _DEBUG
		EnterCriticalSection(&m_csMemLock);
		ofstream out2file(m_csLogPath, ios::app);
		list<SM>::iterator it;
		out2file<<"开始统计泄露的内存:"<<"\n";
		for (it = m_list.begin(); it != m_list.end(); ++it)
		{
			if (it->flg == 1)//正在使用的内存才是泄露
			{
				if (out2file.is_open())
				{
					CString addr;
					addr.Format("0x%p", it->pt);
					out2file<<"CheckMemLeak:检测到内存泄露, 地址是:"<<addr<<", size:"<<it->size<<"\n";
				}
			}
		}
		out2file.close();
		LeaveCriticalSection(&m_csMemLock);
#endif
	};
};

//初始化池
#define pool_init(size) (CMemPool<char>::Instance(size))
//安全的new
#define s_new(size) (CMemPool<char>::Instance()->New(size, __FILE__, __FUNCTION__, __LINE__))
//安全的delete
#define s_delete(p) (CMemPool<char>::Instance()->Delete(p, __FILE__, __FUNCTION__, __LINE__))
见习学术士 2013-05-02
  • 打赏
  • 举报
回复
Compuware Devpartner Studio
shen_wei 2013-05-02
  • 打赏
  • 举报
回复
顶顶,同获求、、、
gijquery4 2013-05-02
  • 打赏
  • 举报
回复
求帮助哦!!!!
需要学习ubuntu系统上YOLOv4的同学请前往:《YOLOv4目标检测实战:原理与源码解析》 【为什么要学习这门课】 Linux创始人Linus Torvalds有一句名言:Talk is cheap. Show me the code. 冗谈不够,放码过来! 代码阅读是从基础到提高的必由之路。尤其对深度学习,许多框架隐藏了神经网络底层的实现,只能在上层调包使用,对其内部原理很难认识清晰,不利于进一步优化和创新。YOLOv4是最近推出的基于深度学习的端到端实时目标检测方法。YOLOv4的实现darknet是使用C语言开发的轻型开源深度学习框架,依赖少,可移植性好,可以作为很好的代码阅读案例,让我们深入探究其实现原理。【课程内容与收获】 本课程将解析YOLOv4的实现原理和源码,具体内容包括:- YOLOv4目标检测原理- 神经网络及darknet的C语言实现,尤其是反向传播的梯度解和误差计算- 代码阅读工具及方法- 深度学习计算的利器:BLAS和GEMM- GPU的CUDA编程方法及在darknet的应用- YOLOv4的程序流程- YOLOv4各层及关键技术的源码解析本课程将提供注释后的darknet的源码程序文件。【相关课程】 除本课程《Windows版YOLOv4目标检测:原理与源码解析》外,本人推出了有关YOLOv4目标检测的系列课程,包括:《Windows版YOLOv4目标检测实战:训练自己的数据集》《Windows版YOLOv4-Tiny目标检测实战:训练自己的数据集》《Windows版YOLOv4目标检测实战:人脸口罩佩戴检测》《Windows版YOLOv4目标检测实战:中国交通标志识别》建议先学习一门YOLOv4实战课程,对YOLOv4的使用方法了解以后再学习本课程。【YOLOv4网络模型架构图】 下图由白勇老师绘制  

16,473

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧