这篇文章是关于实现 malloc() 和 free() 函数的系列文章的一部分。之前,我们实现了一种相当简单的方法,几乎不释放任何内存:一个指针指向最后分配的块,使 free() 能够释放它,但只能释放它。
更好的选择是让最后一个块指向倒数第二个块,倒数第二个块指向倒数第三个块,依此类推,形成一个链表。为了实现这一点,我们创建一个结构体作为块的标题,其中包含指向前一个块的指针:
typedef 结构头 { 结构头*前一个;标题;
登录后复制
此外,指向最后一个块的指针,以前是 void*,现在是 Header* 类型:
标题*最后= NULL;
登录后复制
为了使用这些标头,abmalloc() 会保留足够的内存来存储标头和请求的大小:
void *abmalloc(size_t 大小) { 标头 *header = sbrk(sizeof(标头) + 大小);
登录后复制
通过这种方式,我们使用块的开头来存储必要的信息,例如指向新块之前最后分配的块的指针:
标题->上一个 = 最后一个;
登录后复制
然后,我们更新最后一个指向新区块:
最后 = 标题;
登录后复制
最后,我们返回一个指向用户可以使用的内存的指针。由于 header 指向元数据,我们不能简单地返回它。否则,当用户使用指针时,所有头信息都会被覆盖!相反,我们返回一个指向标题后面的指针。这个指针很容易计算:它是 header 的内存地址加上 header 的大小:
返回标头 + 1;}
登录后复制
注意我们如何将 header 指针加 1。由于指针类型是 Header*,所以增量实际上是 Header 结构体的字节数,而不仅仅是一个字节。指针的类型与指针运算非常相关。
现在我们的内存块一开始就有元数据,我们在释放时需要考虑到这一点。 free() 接收的指针不是指向块的开头,而是指向用户可用的内存。因此,我们需要从用户传递的指针找到块的开始。没有什么是一点指针算术不能解决的:
void abfree(void *ptr) { 标头 *标头 = (标头*) ptr - 1;
登录后复制
如果 header 指向最后分配的块,则前一个块将成为最后一个。这种情况下,我们可以通过brk()将堆中的内存返回给操作系统:
if (标题==最后){ 最后=标题->上一个; brk(标头); }}
登录后复制
这是我们的新 malloc() 和 free() 函数:
typedef 结构头 { 结构头*前一个; 标题; 标头*最后= NULL; 无效* abmalloc(size_t大小){ 标头 *header = sbrk(sizeof(标头) + 大小); 标题->上一个=最后一个; 最后=标题; 返回标头+1; } 无效 abfree(无效 *ptr) { 标头 *标头 = (标头*) ptr - 1; 如果(标题==最后){ 最后=标题->上一个; brk(标头); } }
登录后复制
abmalloc() 和 abfree() 现在可能会稍微提高内存效率,但也不会高很多。动态分配的内存很少像堆栈一样工作,其中最旧的块总是首先被释放。在下一篇文章中,我们将看到如何使用不再使用的旧块的内存。
(这篇文章最初发布为“实现 malloc() 和 free() — 将元数据添加到暂停怀疑中的内存块。”
以上就是实现 malloc() 和 free() — 将元数据添加到内存块的详细内容,更多请关注【创想鸟】其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。
发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2557520.html