实现 malloc() 和 free() — 将元数据添加到内存块

实现 malloc() 和 free() — 将元数据添加到内存块

这篇文章是关于实现 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

(0)
上一篇 2025年3月6日 08:00:50
下一篇 2025年3月6日 08:00:59

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • 使用 typedef

    typedef 是我永远无法回头的事情之一。本质上,它允许对 C 中的现有类型进行别名,并使代码更易于阅读和编写。 以下例为例 struct my_struct { 整数a; 字符b;}void init_my_struct(struct …

    2025年3月6日
    200
  • C 中使用 goto 进行错误处理

    最近,Python Brasil 邮件列表上开始了关于使用异常的原因的讨论。有一次,一位非常有能力的参与者评论了通过函数返回来处理错误是多么困难,就像在 C 中一样。 当你有一个复杂的算法时,每个可能失败的操作都需要一系列的 if 来检查操…

    2025年3月6日
    200
  • C语言中的队列是什么?

    c 中的队列是遵循先进先出(fifo)原则的基本数据结构。这意味着添加到队列中的第一个元素将是第一个被删除的元素。队列在计算机科学中广泛用于各种应用,例如任务调度、图中的广度优先搜索和缓冲数据流。 定义及基本操作 队列通常支持以下主要操作:…

    2025年3月6日
    200
  • 如何使用C++框架在Web应用程序中实现实时通信?

    使用 c++++ 框架实现实时通信时,选择一个合适的框架至关重要,例如 websocket++、boost.asio 或 pistache。使用 websocket++ 作为示例,服务器端设置监听地址和端口,并使用 on_message 处…

    2025年3月6日
    100
  • 转换为相同大小的无符号类型

    介绍 在cdecl中,有这样的枚举: enum cdecl_show { cdecl_show_predefined = 1 << 0, cdecl_show_user_defined = 1 << 1, cdecl…

    2025年3月6日
    200
  • 不同类型 C++ 框架的最佳实践有什么差异?

    不同 c++++ 框架类型的最佳实践各不相同,具体取决于其设计理念和目标受众。web 框架遵循 mvc 架构、restful 设计和使用模板引擎,而测试框架使用单元测试、模拟和 bdd。orm 框架实现对象-关系映射,惰性加载和审计跟踪。d…

    2025年3月6日
    200
  • c语言如何定义头文件

    C 语言中,头文件用于包含共享代码和声明,可重用在不同源文件中。如何定义头文件:1. 创建以 .h 结尾的文件;2. 使用 #ifndef 和 #define 预处理器指令创建宏,确保仅包含一次;3. 在宏内部定义内容,如数据类型、函数声明…

    2025年3月6日
    200
  • c语言如何调用属性

    在 C 语言中,通过使用专属语法调用属性:获取属性值:struct_or_class_name.property_name设置属性值:struct_or_class_name.property_name = new_value 如何使用 C…

    2025年3月6日
    200
  • c语言函数怎么返回

    C 语言函数返回方式有 5 种:直接返回:使用 return 语句返回一个值。返回指针:返回指向一个变量或内存块的指针。通过引用参数返回:修改引用参数的值来返回一个值。返回结构体:返回一个包含多个值的结构体变量。返回 void:当函数不需要…

    2025年3月5日
    200
  • PHP 7.4及以上版本如何使用FFI直接调用SO库?

    PHP直接调用SO库:FFI扩展详解 传统上,PHP调用其他语言编写的SO库需要编写PHP扩展。然而,PHP 7.4版本引入的FFI(外部函数接口)扩展提供了一种更直接、便捷的调用方法。 使用FFI调用SO库示例 以下代码演示了如何使用FF…

    2025年3月4日
    200

发表回复

登录后才能评论