c++定位内存泄露

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_38126105/article/details/85496707
//测试代码
#include "DebugTracer.h"

//主要的思路是:
// 1.重载new,在重载的new中保存new出来的地址,new的文件名(__FILE___),new的行数(__LINE__)
//2.将该new的信息存放在一个容器中,delete时,删除一个,程序结束,还在容器中的指针,就是已经泄露的指针
int main()
{
	int*p = new int;
	delete p;
	int *p1 = new int[10];
    return 0;
}

用来控制debug下有效,release无效

#ifndef __DUBUG_TRACER_H_
#define __DUBUG_TRACER_H_
#ifndef NDEBUG
#include "Tracer.h"

#define new new(__FILE__,__LINE__)
#endif //!NDEBUG
#endif //!__DUBUG_TRACER_H_

1.重载new/delete,容器存放new信息,并在析构时打印

#ifndef __TRACER_H_
#define __TRACER_H_
#include <stdlib.h>
#include <map>
//操作符重载,全局重载
//该函数是自己new的时候,调用的,new[]底层调用的new
void* operator new(size_t size, const char* filename, const long line);
//该函数是第三方,new的时候,调用的。比如dll,库
void* operator new(size_t size);
//delete[] 他是一个单独的函数
void operator delete(void* pointer);
void operator delete[](void* pointer);
class Tracer
{
public:
	Tracer();
	~Tracer();
	class  Entry 
	{
	public:
		Entry(const char* file = nullptr, const long line = 0)
			:m_file(file), m_line(line) {}
		inline const char* File()
		{
			return m_file;
		}
		inline const long Line()
		{
			return m_line;
		}
	private:
		const char* m_file;
		const long m_line;
	};
	class Lock
	{
	public:
		Lock(Tracer& tracer)
			:m_Tracer(tracer)
		{
			m_Tracer.m_count++;
		}
		~Lock()
		{
			m_Tracer.m_count--;
		}
	private:
		Tracer &m_Tracer;
	};
	void Add(void* pointer, const char* file, const long line);
	void Remove(void* pointer);
	void Dump();
	static bool m_Ready; //是防止对象没生成,调用delete,从而导致程序重载,导致崩溃
private:
	std::map<void*, Entry> m_Tracer_Info_Map;
	long m_count; //是防止第三方调用了形成递归,比如new进了void* operator new(size_t size);就会在进Add,然后会再进map中的new,从而无限循环
};

#endif //!__TRACER_H_

实现文件

#include "Tracer.h"
#include "iostream"

Tracer tracer;
//static 全局定义时,需要使用类型名
bool Tracer::m_Ready = false;
void* operator new(size_t size, const char* filename, const long line)
{
	void* p = malloc(size);
	if (Tracer::m_Ready)
	{
		tracer.Add(p, filename, line);
		return p;
	}
	return p;
}
//该函数是别人new的时候,调用的
void* operator new(size_t size)
{
	void* p = malloc(size);
	if (Tracer::m_Ready)
	{
		tracer.Add(p, "Unknow", -1);
		return p;
	}
	return p;
}
void operator delete(void* pointer)
{
	if (Tracer::m_Ready)
	{
		tracer.Remove(pointer);
	}
	free(pointer);
}
void operator delete[](void* pointer)
{
	if (Tracer::m_Ready)
	{
		tracer.Remove(pointer);
	}
	free(pointer);
}
Tracer::Tracer()
{
	Tracer::m_Ready = true;
	m_count = 0;
}


Tracer::~Tracer()
{
	Dump();
	Tracer::m_Ready = false;
}
void Tracer::Add(void* pointer, const char* file, const long line)
{
	if (m_count > 0)
	{
		return;
	}
	Lock(*this);
	Entry temp(file, line);
	m_Tracer_Info_Map.emplace(std::make_pair(pointer, std::move(temp)));
	
}
void Tracer::Remove(void* pointer)
{
	if (m_count > 0)
	{
		return;
	}
	Lock(*this);
	auto iter = m_Tracer_Info_Map.find(pointer);
	if (iter != m_Tracer_Info_Map.end())
	{
		m_Tracer_Info_Map.erase(iter);
	}
}
void Tracer::Dump()
{
	if (!m_Tracer_Info_Map.empty())
	{
		std::cout << "内存泄露" << std::endl;
		for (auto& i : m_Tracer_Info_Map)
		{
			std::cout << i.second.File() << ":" << i.second.Line() << std::endl;
		}
	}
}

猜你喜欢

转载自blog.csdn.net/m0_38126105/article/details/85496707