最近我被问到一个问题,要实现一个非常简单的malloc
,其中包含以下限制和初始条件。
#define HEAP_SIZE 2048
int main()
{
privateHeap = malloc(HEAP_SIZE + 256); //extra 256 bytes for heap metadata
void* ptr = mymalloc( size_t(750) );
myfree( ptr );
return 0;
}
我需要使用提供的确切空间在此处实现mymalloc
和myfree
。 256字节很好地映射到2048位,如果分配了一个字节或者它是空闲的,我可以存储一个位数组。但是,当我与myfree
进行ptr
通话时,我无法分辨开始时分配了多少大小。我不能使用任何额外的位。
我似乎并不认为有办法解决这个问题,但我已经重申可以做到这一点。有什么建议吗?
malloc
s并释放来测试它,并且它没有任何小的内存块。但这并不能保证任何事情。文件中的指南: 关于您的代码的某些指南:
mymalloc
,myrealloc
,myFree
以适用于所有可能的输入。myrealloc
应该像C ++库中的realloc
一样执行以下操作:
void* myrealloc( void* C, size_t newSize )
:
newSize
大于reallocThis
中的大小:
newSize
的块,以便新块的基本指针也是reallocThis
; NULL
指针,并指向内存块
参数reallocThis
保持不变。newSize
较小,realloc
应缩小块的大小,并且应始终成功。newSize
为0,则应该像免费一样工作。reallocThis
为NULL,则应该像malloc
。reallocThis
是已经释放的指针,那么它应该通过返回NULL正常失败myFree
在传递已经释放的指针时不应该崩溃。答案 0 :(得分:5)
malloc实现的一种常见方式是跟踪内存分配的大小,因此free
知道它们的大小是在指针返回malloc
之前将字节大小存储在字节中。所以说你只需要两个字节来存储长度,当malloc
的调用者请求n
个字节的内存时,实际上你会分配n + 2
个字节。然后将长度存储在前两个字节中,并返回一个指向刚刚存储大小的字节的指针。
对于您的算法,一般来说,一个简单而天真的实现是使用链接的空闲内存块列表来跟踪未分配的内存,这些内存块按其在内存中的位置顺序保存。要分配空间,您需要搜索足够大的空闲块。然后,您可以修改空闲列表以排除该分配。要释放一个块,您可以将其添加回空闲列表,合并相邻的空闲块。
现代标准并不是一个很好的malloc实现,但很多旧的内存分配器都是这样工作的。
答案 1 :(得分:4)
您似乎将256字节的元数据视为位图,以逐字节为基础跟踪空闲/正在使用。
我认为以下只是一种可能的选择:
我首先将2048字节堆视为每个2字节的1024“块”。这为每个块提供了2位信息。您可以将第一个视为表示该块是否正在使用,第二个表示后续块是否与当前块相同的逻辑块。
调用free
函数时,使用传递的地址在位图中找到正确的起始点。然后,您将遍历将每个块标记为空的位,直到您到达第二位设置为0的位,指示当前逻辑块的结束(即,下一个2字节块不是当前逻辑块的一部分)。
[哎呀:刚刚注意到罗斯里奇在评论中已经提出了几乎相同的基本想法。]