我正在尝试编写一个简单的池分配器,用于在 C++ 中进行分配和释放,作为大学类(class)任务的一部分。我们得到了对 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++ 指针做一些非常天真的事情,但据我所知,上面的方法应该可行。如果没有,那么我期待着好好的责骂。
哦,正如你所看到的,我没有费心去对齐内存,因为它是一个小任务,据我所知,这对于它的工作来说并不是必需的,它只会让它更快,但这是否可能导致在需要更多内存时读取和写入错误的内存?
最佳答案
你的地址计算不正确
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);
关于c++ - 通过池分配器中的内存地址访问空闲列表节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33734088/