码迷,mamicode.com
首页 > 编程语言 > 详细

c++ 块内存管理

时间:2016-01-01 23:14:30      阅读:523      评论:0      收藏:0      [点我收藏+]

标签:c++;块内存管理;c++知识点综合运用

#pragma once   //头文件

#include<iostream>
#include<string.h>
#include<list>
#include "TypeTraits.hpp"  //类型萃取
#include <stdarg.h>

using namespace std;

struct SaveAdapter//保存适配器 基类
{
	virtual void save(const char* fmt, ...) = 0;//定义可变参数列表的 纯虚函数(用于被子类重写)
};

class ConsoleSaveAdapter : public SaveAdapter //控制台下的保存适配器
{
	virtual void save(const char* fmt, ...);//重写 基类虚函数  将信息输出到屏幕

};

class FileSaveAdapter :public SaveAdapter //基于文件(写入文件)的保存适配器
{
public:
	FileSaveAdapter(const char* filename="MemoryLeakReport.txt");// 构造函数  打开日志文本文件
	~FileSaveAdapter();                                         //析构函数   关闭保存日志文件
	virtual void save(const char* fmt, ...);					//写入信息
protected:
	FileSaveAdapter(const FileSaveAdapter&);					//拷贝构造只声明不定义	
	void operator=(const FileSaveAdapter&);
private:
	FILE *fOut;													//声明文件指针
};

struct BlockInfo												//定义 开辟堆内存信息提取 类
{
	void* _ptr;							//指向堆内存指针
	string _fileName;					//保存/打印内存泄漏信息时的文件名
	int _line;							//......行号
	string _type;						//类型名
	int size;							//大小
	BlockInfo(void* ptr = NULL, char* fileName = "", int num = 0);  //构造函数
};

class Singleton                        //单例模型   (保证全局只有唯一的一个 内存管理 链表)
{
public:
	static Singleton *GetInstance();	//静态 函数  可通过类型名直接调用  (保证对象唯一)
	void* Alloc(size_t size, char* filename, int line);//自己实现 动态开辟内存

	void DeAlloc(void* ptr);			//释放内存
	static void Persistent();			//静态打印信息函数   调用 _persistent() 
	
private:
	Singleton()
	{}
	Singleton(Singleton&);				//
	Singleton& operator=(Singleton&); //只声明不定义
	void _persistent(SaveAdapter* sa); //内部打印信息  函数  可被 Persistent()调用
protected:
	static Singleton* sInstance;     //静态 单例类型指针
	list<BlockInfo> _BlockList;		// 堆内存管理链表(调用<list>库函数中)
};

template<class T>
T* _NEW(size_t size, char* filename, int line)    //模板函数  NEW  模拟new关键字
{
	T* ptr;     
	if (size > 1)
	{
		
		size_t num = sizeof(T)*size;
		if (!TypeTraits<T>::__IsPODType().Get())//类型萃取
		{
			ptr = (T*)Singleton::GetInstance()->Alloc(num + 4, filename, line);//非基本类型多开辟4字节 记录数组类型大小 用于析构时的计数
			*(int*)ptr = num;
			ptr=(T*)((int*)ptr+1);  
		}
		else
			 ptr = (T*)Singleton::GetInstance()->Alloc(num , filename, line);//Singleton 对象的调用

		for (size_t i = 0; i <size; ++i)
		{
			new(ptr + i) T; //new 的初始化列表功能
		}
		return ptr;
	}
	else
		 ptr = (T*)Singleton::GetInstance()->Alloc(sizeof(T), filename, line);

	return new(ptr) T;
}
    //定义宏  (使 NEW的  调用方法接近  关键字 new)
#define NEW(Type)	_NEW<Type>(1,__FILE__,__LINE__)

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

template<class T>
void _DELETE_ARRAY(T* ptr)
{
	
	
	if(!TypeTraits<T>::__IsPODType().Get())
	{	
		size_t num= *((int*)ptr - 1);
	
		for (size_t i = 0; i < num; ++i)
		{
			ptr[i].~T();
		}
	}
	Singleton::GetInstance()->DeAlloc((int*)ptr - 1);
}


#define DELETE(ptr)	_DELETE(ptr)


#define NEW_ARRAY(Type,size)	_NEW<Type>(size, __FILE__, __LINE__)


#define DELETE_ARRAY(ptr)	_DELETE_ARRAY(ptr)
	
	
#include"memorymanagar.h"  //函数定义文件
#include<assert.h>

using namespace std;

BlockInfo::BlockInfo(void* ptr,char* fileName,int num)//构造 BlockInfo
	: _ptr(ptr)
	, _fileName(fileName)
	, _line(num)
{}
Singleton* Singleton::sInstance = NULL; //类中静态变量 必须在类外定义(初始化)
Singleton* Singleton::GetInstance()  
{
	if (sInstance == NULL)
	{
		sInstance = new Singleton;
	}
	return sInstance;
}

void* Singleton::Alloc(size_t size, char* filename, int line)
{
	void * ptr = malloc(size);
	if (ptr)
	{
		BlockInfo tmp(ptr, filename, line); //生成 节点
		_BlockList.push_back(tmp);  //调用库 中链表操作
	}
	return ptr;
}

void Singleton::DeAlloc(void* ptr)
{
	free(ptr);
	if (ptr)
	{

		list<BlockInfo>::iterator it = _BlockList.begin();  //调用迭代器 用于删除节点
		while (it != _BlockList.end())
		{
			if (it->_ptr == ptr)
			{
				
				_BlockList.erase(it);
				return;
			}
			++it;
		}
	}
	assert(0);
}

void Singleton::Persistent()   //外部接口  (打印信息)
{
	FileSaveAdapter file;
	GetInstance()->_persistent(&file);
}
void Singleton::_persistent(SaveAdapter* sa)  //内部函数  (实现打印信息)
{
		int i = 1;
	std::list<BlockInfo>::iterator it = _BlockList.begin();
	while (it != _BlockList.end())
	{
		printf("【内存泄露%d:】ptr:%p, file:%s, line:%d\n",
		i, it->_ptr, it->_fileName.c_str(), it->_line);
		sa->save("【内存泄露%d:】ptr:%p, file:%s, line:%d\n",
			i, it->_ptr, it->_fileName.c_str(), it->_line);
		++it;
	}
}

void ConsoleSaveAdapter::save(const char* fmt, ...) //
{
	va_list args;
	va_start(args, fmt);
	vfprintf(stdout, fmt, args);
	va_end(args);
}

FileSaveAdapter::FileSaveAdapter(const char* filename )
{
	fOut = fopen(filename, "w");
}

FileSaveAdapter::~FileSaveAdapter()
{
	if (fOut)
		fclose(fOut);
}

void FileSaveAdapter::save(const char* fmt, ...)
{
	if (fOut)
	{
		va_list args;
		va_start(args, fmt);
		vfprintf(fOut, fmt, args);
		va_end(args);
	}
}

//类型萃取
#pragma once

#include<iostream>

using namespace std;

struct __TrueType//定义类 普通类型(基本类型的)
{
	bool Get()
	{
		return true;
	}
};

struct __FalseType//定义类 非基本类型
{
	bool Get()
	{
		return false;
	}
};

template <class _Tp>//模板类 (类型萃取)
struct TypeTraits //非基本类型
{
	typedef __FalseType   __IsPODType;//*****************************************************/
};									  //将基本类型类 与非基本类型类 重命名(typedef)为相同名 :__IsPODType
									  //调用__IsPODType().Get() 时编译器会根据TypeTraits<class T> T 的实际类型调用 		 
template <>	//特化基本类型 bool		  //__FalseType	 或 Truetype 的 Get()函数  得到不同 bool值						
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;
};

//主函数 测试文件
#include<iostream>
#include"memorymanagar.h"
//void Test1()
//{
//	int* p1 = (int*)Alloc(sizeof(int)*10, __FILE__, __LINE__);
//	int* p2 = (int*)Alloc(sizeof(int)*10, __FILE__, __LINE__);
//	int* p3 = (int*)Alloc(sizeof(int)*10, __FILE__, __LINE__);
//	int* p4 = (int*)Alloc(sizeof(int)*10, __FILE__, __LINE__);
//
//	Dealloc(p2);
//	Dealloc(p4);
//}

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

	~AA()
	{
		cout << "~AA()" << endl;
	}
};

void Test1()
{
	// new/delete

	// AA* p1 = _NEW<AA>(sizeof(AA), __FILE__,__LINE__);
	//AA* p1 = NEW(AA);// new AA
	//DELETE(p1);	// delete p1;

	//int* p4 = NEW(int);// new AA
	//DELETE(p4);		// delete p1;

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

	int* p3 = NEW_ARRAY(int, 10);
	//DELETE_ARRAY(p3);
}

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

	return 0;
}


c++ 块内存管理

标签:c++;块内存管理;c++知识点综合运用

原文地址:http://shaungqiran.blog.51cto.com/10532904/1730649

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!