快速业务通道

C++内存管理变革(2):最袖珍的垃圾回收器

作者 佚名技术 来源 程序设计 浏览 发布时间 2012-06-29
;(arg1, alloc);
MyClass* objArray = NewArray<MyClass>(count, alloc);

// …
// 现在,不能再访问intArray, obj, objWithArg, objArray等数据了。

内存管理机制

class AutoFreeAlloc
{
public:
enum { BlockSize = 2048 };
private:
struct _MemBlock
{
_MemBlock* pPrev;
char buffer[BlockSize];
};
enum { HeaderSize = sizeof(_MemBlock) - BlockSize };

char* m_begin;
char* m_end;
};

AutoFreeAlloc类与内存管理相关的变量只有两个:m_begin、m_end。单从变量定义来看,基本上很难看明白。但是有了下面这张示意图就容易理解多了:

图 2

整个AutoFreeAlloc申请的内存,通过_MemBlock构成链表。只要获得了链表的头,就可以遍历整个内存链,释放所有申请的内存了。而链表的头(图中标为_ChainHeader),可以通过m_begin计算得到:

_MemBlock* AutoFreeAlloc::_ChainHeader() const
{
return (_MemBlock*)(m_begin - HeaderSize);
}

为了使得_ChainHeader初始值为null,构造函数我们这样写:

AutoFreeAlloc::AutoFreeAlloc()
{
m_begin = m_end = (char*)HeaderSize;
}

★ 下面我们考虑内存分配过程。Alloc过程主要会有三种情况,具体代码为:

void* AutoFreeAlloc::Alloc(size_t cb)
{
if (m_end – m_begin < cb)
{
if (cb >= BlockSize)
{
_MemBlock* pHeader = _ChainHeader();
_MemBlock* pNew = (_MemBlock*)m_alloc.allocate(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;
}

1. 最简单的情况,是当前_MemBlock还有足够的自由内存(free memory),即:

m_end – m_begin >= cb

此时,只需要将m_end前移cb字节就可以了。我们画个示意图如下:

图 3

2. 在当前的_MemBlock的自由内存(free memory)不足的情况下,我们就需要申请一个新的_MemBlock以供使用[5]。申请新的_MemBlock,我们又会遇到两种情况:

a) 申请的字节数(即cb)小于一个_MemBlock所能够提供的内存(即BlockSize)。

这种情况下,我们只需要将该_MemBlock作为新的当前_MemBlock挂到链表中,剩下的工作就和情形1完全类似。示意图如下:

图 4

b) 而在内存申请的字节数(即cb)大于或等于一个Block的字节数时,我们需要申请可使用内存超过正常长度(BlockSize)的_MemBlock。这个新生成的_MemBlock全部内存被用户申请。故此,我们只需要修改_ChainHeader的pPrev指针,改为指向这一块新申请的_MemBlock即可。m_begin、m_end保持不变(当前的_MemBlock还是当前的_MemBlock)。如图:

图 5

★ 下面我们考虑内存释放(Clear)过程。这个过程就是遍历_MemBlock释放所有的_MemBlock的过程,非常简单。代码如下:

void AutoFreeAlloc::Clear()
{
_MemBlock* pHeader = _ChainHeader();
while (pHeader)
{
_MemBlock* pTemp = pHeader->pPrev;
free(pHeader);
pHeader = pTemp;
}
m_begin = m_end = (char*)HeaderSize;
}

自动析构过程

我们知道,C++以及其他面向对象语言为对象引入了构造、析构过程。这是一个了不起的发明。因为只有这样,才能够保证对象从一开始产生以来(刚new出来),到对象销毁这整个过程,它的数据都处于完备状态,是自洽的。

我们知道,C++以及其他面向对象语言为对象引入了构造、析构过程。这是一个了不起的发明。因为只有这样,才能够保证对象

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号