我试图在 C++ 中为一个类编写一个内存分配器,由于某种原因,当程序试图释放它们时,我分配的 block 没有正确保存它们的数据。
基本上有一个包含不同大小内存块的列表 vector 。当请求一部分内存时,会找到一个合适的 block 并将其返回给用户。如果在其中一个列表中找不到合适的 block ,但有一个更大的 block ,则从列表中删除较大的 block ,分成两半,然后将这两个 block 插入到下面的级别中。
该程序还可以通过将内存块重新插入到列表中并寻找它的“伙伴”(当其父 block 被拆分时创建的 block )来尝试合并它们,只要它可以递归地执行它就可以释放内存块.它通过检查 block 的内存地址来做到这一点。
由于分配和空闲调用之间的某种原因,我的内存块正在被更改,我不确定为什么。
分配():
`void *BuddyAllocator::alloc(int length)
{
cout << "Block size " << length << " requested" << endl;
int rounded_length = round_up(length);
if (rounded_length <= available_mem)
{
cout << "Searching for block size " << rounded_length << endl;
bool loop = true;
while (loop)
{
for (int i = 0; i <= FreeList.size(); i++)
{
if (FreeList[i].head != nullptr)
{
BlockHeader *iter = FreeList[i].head;
if (iter->block_size == rounded_length && iter->free)
{
cout << "Suitable block found, returning block "<<iter<<" size: " << iter->block_size << endl;
loop = false;
FreeList[i].remove(iter);
available_mem -= iter->block_size;
return (void *)iter;
}
else if (iter->block_size > rounded_length && iter->free)
{
cout << "Large block found, splitting block size: " << iter->block_size << endl;
split(iter);
break;
}
}
}
}
}
else
{
cout << "Not enough memory available" << endl;
}
return nullptr;
}`
split: `void *BuddyAllocator::split(BlockHeader *block)
{
int level = log2((double)block->block_size / basic_block_size);
BlockHeader *left = block;
int child_size = block->block_size / 2;
left->block_size = child_size;
BlockHeader *right = new ((char *)block + left->block_size) BlockHeader(child_size, true);
FreeList[level].remove(block);
FreeList[level - 1].insert(right);
cout << "inserting right block into level: " << level - 1 << " size: " << child_size << endl;
FreeList[level - 1].insert(left);
cout << "inserting left block into level: " << level - 1 << " size: " << child_size << endl;
}`
自由():
`void BuddyAllocator::free(void *a)
{
BlockHeader *to_free = (BlockHeader *)a;
int level = log2((double)to_free->block_size / basic_block_size); //find level to insert block into
FreeList[level].insert(to_free);
BlockHeader *iter = to_free->next;
cout << "Freeing memory: " << to_free << endl
<< "Block size: " << to_free->block_size << endl;
while (1 == 1)
{
if (((char *)iter == ((char *)to_free + to_free->block_size))) //check addresses to check for match
{
cout << "Joining segments" << endl;
BlockHeader *joined_block = new ((char *)to_free) BlockHeader(to_free->block_size * 2, true);
joined_block->next = nullptr;
FreeList[level].remove(iter);
FreeList[level].remove(to_free);
free(joined_block);
break;
}
else if ((char *)iter == ((char *)to_free - to_free->block_size)) //check addresses to check for match
{
cout << "Joining segments" << endl;
BlockHeader *joined_block = new ((char *)iter) BlockHeader(to_free->block_size * 2, true);
joined_block->next = nullptr;
FreeList[level].remove(iter);
FreeList[level].remove(to_free);
free(joined_block);
break;
}
else if (iter != nullptr)
{
iter = iter->next;
}
else
{
cout << "Buddy not found :(" << endl;
break;
}
}
}`
这是我遇到的错误:
您可以看到,当分配 block 0x7...a410 时,它正确显示该 block 的大小为 1024,但是当我尝试释放相同的地址时,它显示大小为 111138594(真的错了)。它并不总是发生,正如您所看到的,当 block 0x7...a210 在分配和释放时都显示大小为 128。
我的代码看起来不错,并且通过简单的测试(分配一个,释放同一个,仅此而已)它可以工作,但是当我尝试自动分配/释放 block 时,我无法弄清楚为什么它不起作用。任何人都可以帮忙吗?
最佳答案
分配器通常不返回数据结构节点(在您的情况下为 BlockHeader)。他们将其中的空白区域返回为 void *
.如果您的调用者将数据存储在分配器的返回值中,他们将覆盖其字段。
简单的“分配,然后释放”就可以了。问题是如果你使用分配器的返回。
同样,免费时,您需要从 void *
中找到 BlockHeader在其中。通常通过减去字段偏移量或 sizeof(BlockHeader)
来实现。
关于c++ - 为什么我分配的内存块不一致?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60106058/