内存池模型设计探讨

来源:互联网 发布:ida pro 7.0 linux 编辑:程序博客网 时间:2024/05/04 11:43
 

1   引言

我们通常的内存管理方式是申请固定大小的一段内存,并采用链表的方式对其进行管理,这样可能会遇到几个问题:

1、  采用链表方式无法实现小内存的申请;

2、  另一个问题是内存申请边界问题;

3、  无法满足任意大小的内存申请;

4、  无法满足任意数量的内存申请;

我认为一个设计全面的内存池模型应该满足上面的四个条件。

2   内存池结构

2.1内存池模型结构图

3   底层缓冲区的设计

底层的设计是内存池的关键地方,底层设计得第一步先申请一个内存块,然后对内存块进行初始化。下面采用链表得方式对内存块进行初始化:

#define MAX_BLOCKS 1024    //一个DataBlock类最大容纳对象个数1024

class DataBlock

{

public:

       explicit DataBlock(size_type block_size);       //构造函数

       ~DataBlock();                                //析构函数

private:

struct BlockNode

{

       BlockNode* next_;

};

typedef BlockNode *  NodePtr;

const NodePtr end_node() const{ return (NodePtr)0; }

       unsigned char *  base_addr_;  //内存首地址

};

DataBlock::DataBlock(size_type block_size)

{

       base_addr_  = new unsigned char[block_size_ * MAX_BLOCKS];

       /*初始化,生成链表*/

       NodePtr node = head_node_ = (NodePtr)base_addr_;

       head_node_->next_ = end_node();

       for (size_type n = 1; n < MAX_BLOCKS; n++) {

              node->next_ = (NodePtr)(base_addr_ + n*block_size_);

              node = node->next_;

              node->next_ = end_node();

       }

}

上面的过程就是把已分配的内存进行链表化,把每隔block_size_长度的地方作为链表的节点;当外部需要block_size_内存时我们就可以把剩余链表的节点返回给用户,比如下面内存分配函数的实现方法:

void * DataBlock::allocate(size_type block_size)

{

       if (block_size > block_size_)

              return (void*)end_node();

       NodePtr node = head_node_;

       if (head_node_ != end_node() )

              head_node_ = head_node_->next_;

       return (void*)node;

}

Head_node_为链表的头节点,每次分配返回头结点的地址,并且对block_size_进行判断,以免外部的block_size_非法。地址的释放操作如下:

Void DataBlock::deallocate(void * p, size_type block_size)

{

       if (block_size > block_size_)

              return;

       NodePtr node = reinterpret_cast<NodePtr>(p);

       node->next_  = head_node_;

       head_node_   = node;

}

把外部需要释放的内存作为链表的头节点插入链表,就完成内存的回收。

《未完待续》......

原创粉丝点击