项目总结图:

wKiom1eSClGTyo0QAAHYemLBGV4709.png

项目代码:

TypeTraits.hpp

struct __TrueType
{
	bool Get()
	{
		return true;
	}
};

struct __FalseType
{
	bool Get()
	{
		return false;
	}
};

template <class _Tp>
struct TypeTraits
{
	typedef __FalseType   __IsPODType;
};

template <>
struct TypeTraits< bool>
{
	typedef __TrueType     __IsPODType;
};

template <>
struct TypeTraits< char>
{
	typedef __TrueType     __IsPODType;
};

template <>
struct TypeTraits< unsigned char >
{
	typedef __TrueType     __IsPODType;
};

template <>
struct TypeTraits< short>
{
	typedef __TrueType     __IsPODType;
};

template <>
struct TypeTraits< unsigned short >
{
	typedef __TrueType     __IsPODType;
};

template <>
struct TypeTraits< int>
{
	typedef __TrueType     __IsPODType;
};

template <>
struct TypeTraits< unsigned int >
{
	typedef __TrueType     __IsPODType;
};

template <>
struct TypeTraits< long>
{
	typedef __TrueType     __IsPODType;
};

template <>
struct TypeTraits< unsigned long >
{
	typedef __TrueType     __IsPODType;
};

template <>
struct TypeTraits< long long >
{
	typedef __TrueType     __IsPODType;
};

template <>
struct TypeTraits< unsigned long long>
{
	typedef __TrueType     __IsPODType;
};

template <>
struct TypeTraits< float>
{
	typedef __TrueType     __IsPODType;
};

template <>
struct TypeTraits< double>
{
	typedef __TrueType     __IsPODType;
};

template <>
struct TypeTraits< long double >
{
	typedef __TrueType     __IsPODType;
};

template <class _Tp>
struct TypeTraits< _Tp*>
{
	typedef __TrueType     __IsPODType;
};

MemoryManager.h

#pragma once

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
#include<list>
#include<assert.h>
#include<stdarg.h>
#include"TypeTraits.hpp"
using namespace std;

// 保存适配器
class SaveAdapter
{
public:
	virtual void Save(const char* fmt,...) = 0;
};

class ConsoleSaveAdapter:public SaveAdapter
{
public:
	virtual void Save(const char* fmt, ...)
	{
		va_list arg;
		va_start(arg, fmt);
		//int vfprintf ( FILE * stream, const char * format, va_list arg );
		vfprintf(stdout, fmt, arg);
		va_end(arg);
	}
};
class FileSaveAdapter:public SaveAdapter
{
public:
	FileSaveAdapter(const char* filename = "memoryLeakReport.txt")
	{
		_fptr = fopen(filename, "w");
	}
	~FileSaveAdapter()
	{
		if (_fptr)
		{
			fclose(_fptr);
		}
	}
	virtual void Save(const char* fmt, ...)
	{
		if (_fptr)
		{
			va_list arg;
			va_start(arg, fmt);
			vfprintf(_fptr, fmt, arg);
			va_end(arg);
		}
	}
protected:
	FileSaveAdapter(const FileSaveAdapter& f);
	FileSaveAdapter& operator=(FileSaveAdapter& f);
protected:
	FILE* _fptr;
};

struct BlockInfo //内存块信息
{
	void* _ptr;
	string _file;
	int _line;
	BlockInfo(void* ptr, string file, int line)
		:_ptr(ptr)
		, _file(file)
		, _line(line)
	{}
};


	//单例模式
	//封装
	//保证全局中只有一个实例对象
	//很容易被外界所获取到这个实例
class Singleton
{
public:
	static Singleton* GetInstance();
	void* Alloc(size_t size, string file, int line);//分配空间
	void Dealloc(void* ptr);//释放空间

	//持久化
	static void Persistent();
	void _Persistent(SaveAdapter* sa);//打印内存泄漏的内存块信息
private:
	Singleton(){};
	Singleton(const Singleton & s);
	Singleton& operator=(const Singleton &s);
protected:
	list<BlockInfo> _blockList;
	static Singleton* sInstance;
};

#define NEW(type) \
	__NEW<type>(sizeof(type), __FILE__, __LINE__)
#define DELETE(ptr) \
	__DELETE(ptr)
#define NEW_ARRAY(type,num) \
	__NEW_ARRAY<type>(sizeof(type)*num, __FILE__, __LINE__)
#define DELETE_ARRAY(ptr)\
	__DELETE_ARRAY(ptr)


template<class T>
T* __NEW(size_t size, const char* file, int line)
{
	T* ptr = (T*)Singleton::GetInstance()->Alloc(size, file, line);
	//new定位表达式调用构造函数初始化
	return new(ptr)T;
}

template<class T>
void __DELETE(T* ptr)
{
	ptr->~T();
	Singleton::GetInstance()->Dealloc(ptr);
}

template<class T>
T* __NEW_ARRAY(size_t size, const char*file, int line)
{
	bool isPodType = TypeTraits<T>::__IsPODType().Get();
	if (isPodType)
	{
		T* ptr = (T*)Singleton::GetInstance()->Alloc(size, file, line);
		return ptr;
	}
	else
	{
		T* p = (T*)Singleton::GetInstance()->Alloc(size + 4, file, line);
		int num = size / sizeof(T);
		*(int*)p = num;
		T* ptr = (T*)((int*)p + 1);
		//运用new的定位表达式调用构造函数实例化对象
		T* tmp = ptr;
		while (num--)
		{
			new(tmp)T;
			tmp++;
		}
		return ptr;
	}
}

template<class T>
void __DELETE_ARRAY(T *ptr)
{
	bool isPodType = TypeTraits<T>::__IsPODType().Get();
	if (isPodType)
	{
		Singleton::GetInstance()->Dealloc(ptr);
	}
	else
	{
		T* tmp = ptr;
		int* tmp1 = (int*)ptr;
		int num = *(--tmp1);
		//显示的调用num次析构函数
		while (num--)
		{
			tmp->~T();
			tmp++;
		}
		Singleton::GetInstance()->Dealloc(tmp1);
	}
}

MemoryManager.cpp

#include"MemoryManager.h"

void* Singleton::Alloc(size_t size, string file, int line)
{
	void* ptr = malloc(size);
	if (ptr != NULL)
	{
		BlockInfo info(ptr, file, line);
		_blockList.push_back(info);
	}
	return ptr;
}
void Singleton::Dealloc(void* ptr)
{
	free(ptr);
	if (ptr != NULL)
	{
		list<BlockInfo>::iterator it = _blockList.begin();
		while (it != _blockList.end())
		{
			if (it->_ptr == ptr)
			{
				_blockList.erase(it);
				return;
			}
			it++;
		}
		assert(false);
	}
}
void Singleton::_Persistent(SaveAdapter* sa)
{
	list<BlockInfo>::iterator it = Singleton::_blockList.begin();
	while (it != _blockList.end())
	{
		int i=1;
		//printf("ptr:%p\nfile:%s\nline:%d\n", it->_ptr,it->_file.c_str() ,it->_line);
		sa->Save("【内存泄露%d:】ptr:%p, file:%s, line:%d\n",
		i, it->_ptr, it->_file.c_str(), it->_line);
		it++;
		cout << "\n";
	}
}
void Singleton::Persistent()
{
	ConsoleSaveAdapter csa;
	GetInstance()->_Persistent(&csa);

	FileSaveAdapter fsa;
	GetInstance()->_Persistent(&fsa);
}

Singleton* Singleton::sInstance = NULL;
Singleton* Singleton::GetInstance()
{
	if (sInstance == NULL)
	{
		sInstance = new Singleton;
	}
	return sInstance;
}

Test.cpp

#include"MemoryManager.h"

class AA
{
public:
	AA()
	{
		cout << "A()" << endl;
	}
	~AA()
	{
		cout << "~A()"<<endl;
	}
};

void Test1()
{
	AA* p1=NEW(AA);
	DELETE(p1);

	int* p2 = NEW(int);
	DELETE(p2);

	AA*p3 = NEW_ARRAY(AA,10);
	DELETE_ARRAY(p3);

	double* p4 = NEW_ARRAY(double, 8);
	DELETE_ARRAY(p4);
} 

int main()
{
	// 登记一个函数在main函数执行结束以后执行
	atexit(&Singleton::Persistent);

	Test1();
	system("pause");
	return 0;
}


《完》