通过池分配器

时间:2015-11-16 11:17:36

标签: c++ memory-management allocation

我正在尝试编写一个简单的池分配器,用于在c ++中进行分配和释放,作为uni课程任务的一部分。我们得到了git-user floooh的oryol引擎https://github.com/floooh/oryol/blob/master/code/Modules/Core/Memory/poolAllocator.h的引用,因此我尝试通过将池拆分为在需要时分配的水坑来做类似的事情。从一开始,然后随着内存需求的增加而递增。

在我的案例中,每个水坑都维护着自己的免费节点列表,我在创建第一个水坑时已经失败了:当我尝试访问节点结构数据成员时,我遇到了分段错误。下面是我的池分配器类描述以及用于添加水坑的构造函数和函数。我在allocNewPuddle()中的大写锁定“SEGMENTATION FAULT”中注释了它失败,在该函数中的第10行。

课程描述:

template<class T> class memAllocator {
public:
  memAllocator();
  ~memAllocator();

  struct Puddle;

  struct mNode {
    mNode* nextN;
    mNode* prevN;
    uint puddle;
  };

  struct Puddle {
    mNode* headN_free;
    mNode* headN_occ;
  };

  uint numPuddles;
  static const uint nodesInPuddle = 512;
  static const uint maxPuddles = 512;
  Puddle* puddles[maxPuddles];

  uint nodeSize;
  uint elemSize;
  uint puddleStructSize;

  void allocNewPuddle();
  void* allocate();
  void deallocate(void* obj);
  void* findNextFreeNode();
  template<typename... ARGS> T* create(ARGS&&... args);
  void destroy(T* obj);

};

构造

template<class T>
memAllocator<T>::memAllocator() // creates instance of allocator starting with one puddle allocated
{
  this->numPuddles = 0;
  this->nodeSize = sizeof(mNode);
  this->elemSize = nodeSize + sizeof(T);
  this->puddleStructSize = sizeof(Puddle);

  allocNewPuddle();
}

添加一个新的水坑:

template<class T>
void memAllocator<T>::allocNewPuddle() // allocates a new puddle
{
  // allocate memory for one puddle
  assert(numPuddles < maxPuddles);
  Puddle* newPuddle = (Puddle*) malloc(puddleStructSize + nodesInPuddle * elemSize);

  // allocate nodes in free list pointed to by puddle struct
  newPuddle->headN_free = (mNode*) (newPuddle + puddleStructSize + (nodesInPuddle-1)*elemSize);
  for (int i = nodesInPuddle-2; i >= 0; i--) {
    mNode* curNode = (mNode*) (newPuddle + puddleStructSize + i*elemSize);
    // Fails here when attempting to access mNode struct members
    curNode->puddle = numPuddles; // SEGMENTATION FAULT HERE ON FIRST ITERATION
    curNode->prevN = nullptr;
    curNode->nextN = newPuddle->headN_free;
    curNode->nextN->prevN = curNode;
    newPuddle->headN_free = curNode;
  }
  newPuddle->headN_occ = nullptr;
  puddles[numPuddles] = newPuddle;
  numPuddles++;
}

这是我的main.cc:

#include "memAllocator.h"
#include <iostream>

class Test {
public:
  Test();
  ~Test();
  int arr[5];
};

Test::Test() {
  for (int i = 0; i < 5; i++) {
     this->arr[i] = i;
  }
}

Test::~Test() {
  std::cout << "destructor called" << std::endl;
}

int main(int argc, char* argv[]) {
  memAllocator<Test> memPool = memAllocator<Test> ();
  Test* test = memPool.create();
  for (int i = 0; i < 5; i++) {
    std::cout << test->arr[i] << std::endl;
  }
  memPool.destroy(test);
  for (int i = 0; i < 5; i++) {
    std::cout << test->arr[i] << std::endl;
  }
}

我的猜测是我正在用c ++指针做一些非常天真的事情,但据我所知,上面应该有用。如果没有,那么我期待好好的责骂。

哦,正如你所看到的那样,我并不打算调整内存,因为它是一个很小的任务,而且据我所知,它不是必不可少的工作它只会使它更快,但这可能会导致是否需要读取和写入错误的内存?

1 个答案:

答案 0 :(得分:0)

您的行地址计算错误

mNode* curNode = (mNode*) (newPuddle + puddleStructSize + i*elemSize);

newPuddle 是Puddle指针,但您尝试添加字节。因此,您的新地址远远超出分配的内存缓冲区的末尾。因此,您必须将显式强制转换添加到字节指针(char,uint8_t等)

mNode* curNode = (mNode*) ((char*)newPuddle + puddleStructSize + i*elemSize);

您也必须修复此行

newPuddle->headN_free = (mNode*) (newPuddle + puddleStructSize + (nodesInPuddle-1)*elemSize);