我在C中构建了一个简单的内存池,我也实现了在这个池中实现内存块的能力。
内存块本身非常简单,只是一个带有free flag和size属性的双向链表。
我现在要做的是创建一个函数,该函数接收指向我的内存池的指针并对内部的内存块进行碎片整理,以便分配的(free == 0)块位于池的开头,并且释放的块是在游泳池尽头。
例如,如果在调用我的碎片整理功能之前,我有像这样构造的内存块:
Block Size: 25 (41 w/ header), Free: 1
Block Size: 100 (116 w/ header), Free: 0
Block Size: 25 (41 w/ header), Free: 1
Block Size: 100 (116 w/ header), Free: 0
Block Size: 100 (116 w/ header), Free: 0
Block Size: 54 (70 w/ header), Free: 1
然后在调用我的函数后,块将按如下方式排列:
Block Size: 100 (116 w/ header), Free: 0
Block Size: 100 (116 w/ header), Free: 0
Block Size: 100 (116 w/ header), Free: 0
Block Size: 25 (41 w/ header), Free: 1
Block Size: 25 (41 w/ header), Free: 1
Block Size: 54 (70 w/ header), Free: 1
我已经尝试构建该函数但是我遇到了一个问题,在它周围移动正确的块似乎是在调用该函数后这是我的输出:
Block Size: 100 (116 w/ header), Free: 0
Block Size: 25 (41 w/ header), Free: 1
Block Size: 100 (116 w/ header), Free: 0
Block Size: 1744830464 (1744830480 w/ header), Free: 21
我不确定该功能在哪里执行不正确的操作,所以希望有人可以为我阐明这一点。
我的碎片整理功能:
void defragment(Pool* pool)
{
if(pool && pool->root)
{
Block* current = pool->root;
while(current)
{
if(!current->free)
{
Block* current_prev = current->prev;
if(current_prev && current_prev->free)
{
Block* prev_prev = current_prev->prev;
int new_block_size = current_prev->size;
Block* moved_current = memmove(current_prev, current, sizeof(Block) + current->size);
if(!moved_current)
{
printf("couldn't move memory\n");
}
else
{
Block* new_block = initBlock((((char*)moved_current) + sizeof(Block) + moved_current->size), new_block_size);
new_block->prev = moved_current;
new_block->next = moved_current->next;
moved_current->prev = prev_prev;
moved_current->next = new_block;
if(prev_prev)
{
prev_prev->next = moved_current;
}
current = moved_current;
continue;
}
}
}
current = current->next;
}
//Join Contiguous Blocks
}
}
对initBlock函数的调用只需要一个内存地址,将其视为一个Block结构,然后将free属性设置为true,将size属性设置为给定的大小。
我正在使用带有-std = C99标志的GCC编译器。
答案 0 :(得分:1)
在交换一对块之后,您似乎没有更新下一个块的prev
字段。因此,当您前进到下一个块并检查前一个块是否空闲时,您将访问垃圾。你需要像
if (newblock->next)
new_block->next->prev = new_block;
在上面的else
部分。
其他问题