自主实现动态内存管理,利用malloc/free模拟C++中的new/delete,利用单链表检查申请内存与释放内存的情况.
当是为内置类型申请内存空间时,malloc/free可以完成new/delete的功能;而当为自定义类型申请内存空间或释放空间,对于new/delete来说,是会调用该类型的构造函数与析构函数的,所以在这种情况下,malloc/free需要与new的定位表达式结合起来使用,因为当malloc出内存时,说明已经有对象存在了,而new的定位表达式正是可以在对象存在后,进行构造函数的调用。
//LIst.hpp
#ifndef _LIST_H_
#define _LIST_H_
#include<iostream>
using namespace std;
template<class T>
struct Node
{
T _value;
Node<T>* _next;
Node<T>(const T& value)
: _value(value)
, _next(NULL)
{}
};
template<class T>
class List
{
public:
List()
:_head(NULL)
{}
void PushBack(const T&data);
Node<T>* Find(const T&data);
void Remove(Node<T>*del);
void Print();
private:
Node<T>*_head;
};
template<class T>
void List<T>::PushBack(const T&data)
{
Node<T>*tmp = new Node<T>(data);
if (_head == NULL)
{
_head = tmp;
return;
}
Node<T>*begin = _head;
while (begin->_next)
{
begin = begin->_next;
}
begin->_next = tmp;
}
template<class T>
Node<T>* List<T>::Find(const T&data)
{
if (_head == NULL)
{
return NULL;
}
Node<T>*begin = _head;
while (begin)
{
if (begin->_value== data)
{
return begin;
}
begin = begin->_next;
}
return NULL;
}
template<class T>
void List<T>::Remove(Node<T>*del)
{
if (_head == NULL)
{
return;
}
Node<T>*begin = _head;
Node<T>*prev = _head;
while (begin)
{
if (del == begin)
{
if (del == _head)
{
_head = _head->_next;
}
else
{
prev->_next = begin->_next;
}
delete del;
return;
}
prev = begin;
begin = begin->_next;
}
}
template<class T>
void List<T>::Print()
{
Node<T>*begin = _head;
while (begin)
{
cout << begin->_value<<" ";
begin = begin->_next;
}
}
#endif //_LIST_H
//MemoryBlockInfo.h
#ifndef _MEM_H_
#define _MEM_H_
#include"List.hpp"
#include<string>
struct MemoryBlockInfo//内存块信息
{
void* _ptr;
string _filename;
int _line;
MemoryBlockInfo(void*ptr = NULL, string filename = "", int line = 0);
bool operator==(const MemoryBlockInfo&m);
friend ostream& operator<<(ostream& out, MemoryBlockInfo&m);
};
class MemoryManage//单例模式,管理链表
{
public:
static MemoryManage* GetInStance()
{
if (_InStance == NULL)
{
_InStance = new MemoryManage();
}
return _InStance;
}
void* __NEW(size_t size, string filename, int line);//申请空间
void __DELETE(void*ptr);//释放空间
void PPrint()
{
_infos.Print();
}
private:
MemoryManage()
{}
static MemoryManage* _InStance;
List<MemoryBlockInfo>_infos;
};
/*****************************************************************************************************/
//对于单个对象
template<class T>
inline T* _NEW(size_t size, string filename, int line)
{
//对于自定义类型,会调用构造函数;但在这里对象已经产生,所以需要用new的定位表达式来调构造函数
return new((T*)MemoryManage::GetInStance()->__NEW(size, filename, line))T;
}
template<class T>
inline void _DELETE(T*ptr)//释放空间
{
ptr->~T();//对于自定义类型,会调用析构函数
MemoryManage::GetInStance()->__DELETE(ptr);
}
#define NEW(type) _NEW<type>(sizeof(type), __FILE__, __LINE__)
#define DELETE(ptr) _DELETE(ptr)
/****************************************************************************************************/
//对于对象数组
template<class T>
inline T* _NEW_ARRAY(size_t num, string filename, int line)
{
//对于对象数组,在申请空间时,需多申请4个字节的空间,存储数组元素的个数,即有多少个对象
T*ptr = (T*)(MemoryManage::GetInStance()->__NEW(sizeof(T)*num + 4, filename, line));
*(int*)ptr = num;
T*Retptr = (T*)((int*)ptr + 1);
for (int i = 0; i <(int) num; i++)
{
new(&Retptr[i])T;//调用构造函数
}
return ptr;
}
template<class T>
inline void _DELETE_ARRAY(T*ptr)
{
int num = *(int*)ptr;
T*Retptr = (T*)((int*)ptr + 1);
for (int i = 0; i < num; i++)
{
Retptr[i].~T();//调用析构函数
}
MemoryManage::GetInStance()->__DELETE(ptr);
}
#define NEW_ARRAY(type,num) _NEW_ARRAY<type>(num,__FILE__,__LINE__)
#define DELETE_ARRAY(ptr) _DELETE_ARRAY(ptr)
#endif //_MEM_H_
/****************************************************************************************************/
//MemoryBlockInfo.cpp
#include"MemoryBlockInfo.h"
MemoryBlockInfo::MemoryBlockInfo(void*ptr, string filename, int line)
:_ptr(ptr)
, _filename(filename)
, _line(line)
{}
bool MemoryBlockInfo::operator==(const MemoryBlockInfo&m)
{
return _ptr == m._ptr;
}
ostream& operator<<(ostream& out, MemoryBlockInfo&m)
{
out << "ptr:" << m._ptr << endl;
out << "filename:" << m._filename << endl;
out << "line:" << m._line << endl;
return out;
}
void* MemoryManage::__NEW(size_t size, string filename, int line)
{
void*ptr = malloc(size);
if (ptr)
{
_infos.PushBack(MemoryBlockInfo(ptr, filename, line));
}
return ptr;
}
void MemoryManage::__DELETE(void*ptr)
{
if (ptr)
{
Node<MemoryBlockInfo>*del = _infos.Find(MemoryBlockInfo(ptr));
_infos.Remove(del);
}
free(ptr);
}
//main.cpp
#define _CRT_SECURE_NO_WARNINGS
#include"MemoryBlockInfo.h"
class String//自定义String类
{
public:
String(char* ptr = "")
:_ptr(new char[strlen(ptr) + 1])
{
cout << "String()" << endl;
strcpy(_ptr, ptr);
}
~String()
{
if (_ptr)
{
delete []_ptr;
}
cout << "~String()" << endl;
}
private:
char* _ptr;
};
void Test()
{
int*p1 = NEW(int);
String*p2 = NEW(String);
DELETE(p1);
DELETE(p2);
String*p3 = NEW_ARRAY(String,3);
DELETE_ARRAY(p3);
MemoryManage::GetInStance()->PPrint();
}
MemoryManage* MemoryManage::_InStance = NULL;//初始化静态数据
int main()
{
Test();
system("pause");
return 0;
}