C++中的垃圾回收和内存管理最开始的时候看到了许式伟的内存管理变革系列,看到性能测试结果的时候,觉得这个实现很不错,没有深入研究其实现。现在想把这个用到自己的一个项目中来,在linux下编译存在一些问题,所以打算深入研究一下。 讨论C++内存管理的有两个主要的博客,一个是许式伟的系列,(CSDN: http://blog.csdn.net/xushiweizh/article/details/1388982,许式伟个人空间:http:///gc-allocator-summary);另一个是CppExplore的一个内存管理系列(http://www./CppExplore/archive/2008/02/18/42890.html). 主要来研究许式伟的内存管理。 学习许式伟的内存管理器实现,参考 gc_1 gc_2 gc_1和gc_2的代码, // simple_gc.h #ifndef SIMPLE_ALLOC_H_ #define SIMPLE_ALLOC_H_ #include <cstdlib> /* malloc, free, rand */ #include <new> template <class Type> struct DestructorTraits { static void Destruct(void* pThis) { ((Type*)pThis)->~Type(); } }; typedef void (*FnDestructor)(void* pThis); class SimpleAlloc { public: //注意这里提供的参数fnDestroy,它是为那些具备垃圾回收能力的allocator需要提供。 void* Alloc(size_t cb, FnDestructor fnDestroy = NULL) { return malloc(cb); } //注意这里有看似多余的参数cb,这完全是为了和后续提供的allocator规格一致的需要。 void Free(void* data, size_t cb) { free(data); } }; // 类似于new Type template <class Type, class AllocType> inline Type* New(AllocType& alloc) { void* obj = alloc.Alloc(sizeof(Type), DestructorTraits<Type>::Destruct); return new(obj) Type; } // 类似于new Type(arg1) template <class Type, class ArgType1, class AllocType> Type* New(ArgType1 arg1, AllocType& alloc) { void* obj = alloc.Alloc(sizeof(Type), DestructorTraits<Type>::Destruct); return new(obj) Type(arg1); } // 类似于new Type[count] template <class Type, class AllocType> Type* NewArray(size_t count, AllocType& alloc) { void* obj = alloc.Alloc(sizeof(Type)*count, DestructorTraits<Type>::Destruct); return new(obj) Type[count]; } #endif /* SIMPLE_ALLOC_H_ */
auto_alloc.h和auto_alloc.cpp #ifndef AUTO_ALLOC_H_ #define AUTO_ALLOC_H_ #include <cstdlib> /* malloc, free, rand */ #include <new> typedef void (*FnDestructor)(void* pThis); /* class AutoAlloc { public: ~AutoAlloc(); // 析构函数。自动调用Clear释放内存 void* allocate(size_t cb); // 类似于malloc(cb) void* allocate(size_t cb, FnDestructor fn); // 申请内存并指定析构函数 void clear(); // 析构并释放所有分配的对象 }; */ class AutoAlloc { public: enum { BlockSize = 2048 }; private: struct _MemBlock { _MemBlock* pPrev; char buffer[BlockSize]; }; enum { HeaderSize = sizeof(_MemBlock) - BlockSize }; char* m_begin; char* m_end; _MemBlock* _ChainHeader() const { return (_MemBlock*)(m_begin - HeaderSize); } struct _DestroyNode { _DestroyNode* pPrev; FnDestructor fnDestroy; }; _DestroyNode* m_destroyChain; public: AutoAlloc(); ~AutoAlloc(); // 析构函数。自动调用Clear释放内存 void* Alloc(size_t cb); // 类似于malloc(cb) void* Alloc(size_t cb, FnDestructor fn); // 申请内存并指定析构函数 void Clear(); // 析构并释放所有分配的对象 }; template <class Type> struct DestructorTraits { static void Destruct(void* pThis) { ((Type*)pThis)->~Type(); } }; // 类似于new Type template <class Type, class AllocType> inline Type* New(AllocType& alloc) { void* obj = alloc.Alloc(sizeof(Type), DestructorTraits<Type>::Destruct); return new(obj) Type; } // 类似于new Type(arg1) template <class Type, class ArgType1, class AllocType> Type* New(ArgType1 arg1, AllocType& alloc) { void* obj = alloc.Alloc(sizeof(Type), DestructorTraits<Type>::Destruct); return new(obj) Type(arg1); } // 类似于new Type[count] template <class Type, class AllocType> Type* NewArray(size_t count, AllocType& alloc) { void* obj = alloc.Alloc(sizeof(Type)*count, DestructorTraits<Type>::Destruct); return new(obj) Type[count]; } #endif /* AUTO_ALLOC_H_ */
#include "auto_alloc.h" #include <cstdio> AutoAlloc::AutoAlloc() { m_begin = m_end = (char*)HeaderSize; m_destroyChain = NULL; } void* AutoAlloc::Alloc(size_t cb) { if(m_end - m_begin < cb) { if (cb >= BlockSize) { _MemBlock* pHeader = _ChainHeader(); _MemBlock* pNew = (_MemBlock*)malloc(HeaderSize + cb); if (pHeader) { pNew->pPrev = pHeader->pPrev; pHeader->pPrev = pNew; } else { m_end = m_begin = pNew->buffer; pNew->pPrev = NULL; } return pNew->buffer; } else { _MemBlock* pNew = (_MemBlock*)malloc(sizeof(_MemBlock)); pNew->pPrev = _ChainHeader(); m_begin = pNew->buffer; m_end = m_begin + BlockSize; } } return m_end -= cb; } void AutoAlloc::Clear() { // destroy printf("destroy\n"); while (m_destroyChain) { m_destroyChain->fnDestroy(m_destroyChain + 1); m_destroyChain = m_destroyChain->pPrev; } // free memory printf("free memory\n"); _MemBlock* pHeader = _ChainHeader(); while (pHeader) { _MemBlock* pTemp = pHeader->pPrev; free(pHeader); pHeader = pTemp; } m_begin = m_end = (char*)HeaderSize; } void* AutoAlloc::Alloc(size_t cb, FnDestructor fn) { _DestroyNode* pNode = (_DestroyNode*)Alloc(sizeof(_DestroyNode) + cb); pNode->fnDestroy = fn; pNode->pPrev = m_destroyChain; m_destroyChain = pNode; return pNode + 1; } AutoAlloc::~AutoAlloc() { Clear(); }
测试代码这里给出一份就可以了, //#include "simple_gc.h" #include "auto_alloc.h" #include <cstdio> class MyClass { public: int a; public: MyClass(int t=52):a(t){} ~MyClass(){} void Print() { printf("%d\n",a); } }; int main() { // SimpleAlloc alloc; AutoAlloc alloc; int count = 5; int* intArray = NewArray<int>(count, alloc); for(int i=0;i<count;i++) { intArray[i] = i+1; } for(int i=0;i<count;i++) { printf("%d ",intArray[i]); } printf("\n"); MyClass* obj = New<MyClass>(alloc); obj->Print(); int arg1 = 1024; MyClass* objWithArg = New<MyClass>(arg1, alloc); objWithArg->Print(); alloc.Clear(); // MyClass* objArray = NewArray<MyClass>(count, alloc); return 0; }
gc_3 gc_4 gc_5 gc_6 gc_7 gc_8 虽然他的代码可以下载,但我在linux使用的时候出现各种问题,由于他包含了多线程模型的支持,代码也复杂了一些,需要继续研究。 代码可以在linux下编译,在boost-memory-xx/libs/memory/build/下面有Makefile文件,Makefile.li32表示linux 32bit版本的makefile. 在编译之前还是需要做几个小的修改,一个是关于memcpy,在basic.hpp里面添加#include <cstring>,另一个是_alloca函数,添加#include <cstdlib>。 然后编译得到的为动态库文件,libboost-memory.so,在build/Debug下面。 |
|