malloc底层原理实现

2023-11-10

使用过c语言的都知道malloc是一个动态分配内存的函数,还可以通过free释放内存空间。
如果我们想分析一下malloc的源码,这其实不是一会就能看懂的,但是我们可以讨论一下malloc的简单实现。
在这之前,我们先来看一下虚拟内存空间。
这里写图片描述
虚拟内存空间时操作系统实现内存管理的一种机制。操作系统为每个进程维护一个虚拟内存空间。操作系统会将虚拟内存和实际的物理内存进行映射,CPU芯片上叫做存储器管理单元(Memory Management Unit,MMU)的专用硬件,利用存放在主存中的查询表来动态翻译虚拟地址,该表的内容是由操作系统管理。虚拟内存使得用户感觉内存空间时连续的,同时给进程提供独占内存的假象。
我们可以看到虚拟内存空间的顶部是内核管理的内存空间,下面则是用户的内存空间,用户空间无权访问内核的内存空间。
我们可以看到一个区域,运行时堆。我们可以看到运行时堆上面还有一块黑色部分,这就是还未映射的内存。
这里写图片描述
在已经映射的内存空间结尾有一个break指针,这个指针下面是映射好的内存,可以访问,上面则是未映射的访问,不能访问。可以通过系统调用sbrk(位移量)能一定brk指针的位置,同时返回brk指针的位置,达到申请内存的目。brk(void *addr)系统调用可以直接将brk设置为某个地址,成功返回0,不成功返回-1。而rlimit则是限制进程堆内存容量的指针。
在操作系统角度来看,分配内存有两种方式,一种是采用推进brk指针来增加堆的有效区域来申请内存空间,还有一种是采用mmap是在进程的虚拟地址空间中(堆和栈中间,称为文件映射区域的地方)找一块空闲的虚拟内存。这两种方式都是分配虚拟内存,只有当第一次访问虚拟地址空间时,操作系统给分配物理内存空间。
malloc是采用brk的方式来动态分配内存。
那么来谈一下空间内配的实现问题。
其中一种是隐式链表,实际上是数组,malloc分配空间必然有一个数据结构,允许它来区分边界,区分已分配和空间的空间,数据结构中包含一个头部信息和有效载荷,有效载荷的首地址就是malloc返回的地址,可能在尾部还有填充,为了保持内存对齐。头部相当于该数据结构的元数据,其中包含了块大小和是否是空闲空间的信息,这样可以根据头地址和块大小的地址推出下一个内存块的地址,这就是隐式链表。

malloc内存分配原理

malloc基本的实现原理就是维护一个内存空闲链表,当申请内存空间时,搜索内存空闲链表,找到适配的空闲内存空间,然后将空间分割成两个内存块,一个变成分配块,一个变成新的空闲块。如果没有搜索到,那么就会用sbrk()才推进brk指针来申请内存空间。
搜索空闲块最常见的算法有:首次适配,下一次适配,最佳适配。
首次适配:第一次找到足够大的内存块就分配,这种方法会产生很多的内存碎片。
下一次适配:也就是说等第二次找到足够大的内存块就分配,这样会产生比较少的内存碎片。
最佳适配:对堆进行彻底的搜索,从头开始,遍历所有块,使用数据区大小大于size且差值最小的块作为此次分配的块。

合并空闲块

在释放内存块后,如果不进行合并,那么相邻的空闲内存块还是相当于两个内存块,会形成一种假碎片。所以当释放内存后,我们需要将两个相邻的内存块进行合并。

显式空闲链表

还有一种实现方式则是采用显示空闲链表,这个是真正的链表形式。在之前的有效载荷中加入了之前前驱和后驱的指针,也可以称为双向链表。维护空闲链表的的方式第一种是用后进先出(LIFO),将新释放的块放置在链表的开始处。另一种方法是按照地址的顺序来维护。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

malloc底层原理实现 的相关文章

  • 华为OD机试真题-API集群负载统计-Java-OD统一考试(C卷)

    题目描述 某个产品的RESTful API集合部署在服务器集群的多个节点上 近期对客户端访问日志进行了采集 需要统计各个API的访问频次 根据热点信息在服务器节点之间做负载均衡 现在需要实现热点信息统计查询功能 RESTful API的由多
  • 我可以要求内核填充(故障)一系列匿名页面吗?

    在Linux中 使用C 如果我通过以下方式请求大量内存malloc或类似的动态分配机制 很可能支持返回区域的大多数页面实际上不会映射到我的进程的地址空间 相反 每次我第一次访问其中一个分配的页面时都会发生页面错误 然后内核将映射到 匿名 页
  • 在 c 中使用 malloc 实现堆栈 [初学者]

    出于学习目的 我正在用 c 语言实现一个堆栈及其函数 我添加了一些小的附加功能来第一次使用 malloc 并尝试正确理解它 我编写了一个最初创建堆栈结构的函数 该函数的返回值是一个具有已分配内存的新结构 在返回值应该是结构的函数中处理 ma
  • 对指针调用 free 两次

    我在讲座中被教导 召唤free 两次使用指针真的非常非常糟糕 我知道这是一个很好的做法 将指针设置为NULL 在释放它之后 然而 我仍然没有听到任何关于为什么会这样的解释 据我了解 方法malloc 有效 从技术上讲 它应该跟踪它已分配并供
  • 从c中的数组中删除偶数

    你好 我正在尝试大约 2 个小时来创建一个程序 该程序将从 c 中的动态分配数组 使用 malloc 中删除偶数 有人可以帮我提供一些提示或创建代码吗 附注这是我在这里的第一个主题 所以请随时给我一些关于如何正确发布问题的提示 假设您已经动
  • 程序不会因堆溢出而崩溃

    我写了以下程序 include
  • 在 C 中 Malloc 一个二维数组[重复]

    这个问题在这里已经有答案了 每次我首先为二维数组分配内存时 我都会创建一个数组int 然后使用 for 为每个元素分配内存 例如 int arr malloc N sizeof int for i 0 i lt N i arr i mall
  • 如何在c中找到内存分配的最大限制

    我想确定我可以在计算机中分配的最大内存限制是多少 这是我为此任务编写的代码 include
  • 如何在 JavaScript 中有效地将大块细分为许多大小为 2 的幂的小块

    建设关闭这个答案 https stackoverflow com questions 66253424 how to efficiently segment a large block of predefined size into sma
  • 为什么我们要转换 malloc 的返回值? [复制]

    这个问题在这里已经有答案了 有人可以向我解释一下为什么有些程序员在 malloc 前面使用 char 吗 我知道它返回 void 但为什么我希望它只返回 char 内存 抱歉 我只是编程新手 谢谢 无需转换返回值malloc因为它的返回类型
  • C/C++ 的多线程内存分配器

    我目前有大量的多线程服务器应用程序 并且我正在寻找一个好的多线程内存分配器 到目前为止 我在以下两点之间左右为难 太阳乌梅 谷歌的tcmalloc 英特尔的线程构建块分配器 埃默里 伯杰的宝藏 据我所知 hoard 可能是最快的 但我在今天
  • Linux中分配特定地址

    我想在Linux进程中的特定地址分配一块内存 实际上我想做一些类似的事情 我会有进程号 每个进程都会调用库 由我编写 中的初始化函数 该函数将在进程的地址空间中分配一些内存 它将存储进程相关信息 这将由每个进程完成 一旦分配了该内存 程序就
  • malloc + size_t * 3 的地址对于任何类型都是对齐的吗?

    我正在构建一种动态数组 向量 但不是嵌入数据 通常是void 变成struct vector 我正在预留空间struct vector 一大块字节 使用数组的示例size t s include
  • glibc 已弃用的 __malloc_hook 功能的替代方案

    我正在为 C 编写一个内存分析器 并为此拦截对malloc realloc and free通过 malloc hooks 函数 不幸的是 这些已被弃用 因为它们在多线程环境中表现不佳 我找不到描述实现相同目标的替代最佳实践解决方案的文档
  • 堆内存和Slab分配

    我很困惑heap and free list 我有几个问题 我对C中malloc的工作原理有自己的理解 如果我错了 请纠正我 堆内存是否被组织为数据的链表 空闲列表 块 堆内存和空闲列表有区别吗 我对存储分配的理解 有待改进 当我们调用ma
  • 为什么 new()/delete() 比 malloc()/free() 慢?

    为什么new delete 比malloc free 慢 EDIT 感谢到目前为止的回答 如果您有new 和delete 的标准C 实现规范 请指出 谢谢 看一下这段C代码 struct data pd malloc sizeof stru
  • 是否可以用 C 语言编写 malloc 的一致实现?

    这是后续字符数组可以与任何数据类型一起使用吗 https stackoverflow com questions 38510557 我了解动态内存和 malloc 的常见实现 可以在以下位置找到参考资料维基百科 https en wikip
  • 为什么我不应该对不是由 malloc() 分配的变量调用 free() ?

    我在某处读到 使用它是灾难性的free删除不是通过调用创建的对象malloc 这是真的 为什么 这是未定义的行为 永远不要尝试它 让我们看看当您尝试时会发生什么free 自动变量 堆管理器必须推断出如何获取内存块的所有权 为此 它要么必须使
  • Visual C++ free 和 malloc 的线程安全性?

    有谁知道 free 和 malloc 在 Visual C 2010 上是否是线程安全的 我遇到了奇怪的问题 内存被损坏 我几乎认为这是唯一的可能性 有谁知道安全装置是否可以打开和关闭以及如何打开和关闭 前提是您链接的是线程安全库 http
  • 为什么这种故意错误地使用 strcpy 不会严重失败?

    为什么下面的C代码使用strcpy对我来说工作得很好吗 我试图通过两种方式让它失败 1 我尝试过strcpy从字符串文字到分配的内存 该内存太小而无法容纳它 它复制了整个事情并且没有抱怨 2 我尝试过strcpy来自一个不是的数组NUL 终

随机推荐

  • 【LeetCode - 658】找到 K 个最接近的元素

    文章目录 1 题目描述 2 解题思路 3 解题代码 1 题目描述 2 解题思路 题目给定的函数返回的是 List 类型 List 有一个方法和字符串类似 为 subList a b 返回 list 区间 a b 的子序列 先把给定的 arr
  • xshell以及xftp免费版

    https www netsarang com zh free for home school
  • GdiPlus

    GDI是Graphics Device Interface的缩写 含义是图形设备接口 它的主要任务是负责系统与绘图程序之间的信息交换 处理所有Windows程序的图形输出 在Windows操作系统下 绝大多数具备图形界面的应用程序都离不开G
  • C ~ 文件读写

    一个文件 无论它是文本文件还是二进制文件 都是代表了一系列的字节 如何创建 打开 关闭文本文件或二进制文件 C 语言不仅提供了访问顶层的函数 也提供了底层 OS 调用来处理存储设备上的文件 打开文件 可以使用 fopen 函数来创建一个新的
  • 二叉树-判断另一棵树的子树(Java)

    另一棵的子树 力扣572题 题目 给你两棵二叉树 root 和 subRoot 检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树 如果存在 返回 true 否则 返回 false 二叉树 tree 的一棵子树包括 t
  • 关于qt.qpa.plugin: Could not load the Qt platform plugin “windows“ in ““ even though it was found.问题

    将如下三个文件 Anaconda3 Lib site packages PySide2 plugins platforms qminimal dll Anaconda3 Lib site packages PySide2 plugins p
  • HTML标签的语法格式

    HTML 中的标签就像关键字一样 每个标签都有自己的语义 含义 例如 p 标签代表段落 b 标签代表加粗 根据标签的不同 浏览器会使用不同的方式展示标签中的内容 在实际开发中 有时我们也将 HTML 标签称为 HTML 元素 HTML 标签
  • 在Makefile中无缝连接字符串

    今天在写Makefile时 忽然遇到了一个问题 如何把几个字符串无缝的连接起来 我自然而然的想到了使用 比如 1 2 3 4 5 6 7 8 9
  • IDEA实用插件

    目录 1 Convert YAML and Properties File 2 GitToolBox 3 JPA Buddy 4 Translation 5 iBATIS MyBatis plugin 6 lombok 7 Backgrou
  • Docker 的使用

    docker 的使用 什么是镜像 镜像是一个文件系统 提供了容器运行时需要用到的文件和参数配置 相当于安装操作系统时需要用到 ISO 文件 1 创建docker镜像 并放在容器中 创建自己的镜像 docker create it ubunt
  • PS透明屏,在科技展示中,有哪些优点展示?

    PS透明屏是一种新型的显示技术 它将传统的显示屏幕与透明材料相结合 使得屏幕能够同时显示图像和透过屏幕看到背后的物体 这种技术在商业展示 广告宣传 产品展示等领域有着广泛的应用前景 PS透明屏的工作原理是利用透明材料的特性 通过控制屏幕上的
  • Mysql -- 设置中国时区时间

    Mysql 设置中国时区时间 查看mysql的时区设置 mysql gt show variables like time zone 修改mysql的时区设置 注 mysql的默认时区是UTC 8 00是中国所在时区 东八区 mysql g
  • Leetcode 21. 合并两个有序链表

    Leetcode 21 合并两个有序链表 1 问题分析 2 问题解决 3 总结 1 问题分析 题目链接 https leetcode cn com problems merge two sorted lists 本质上就是一个链表操作问题
  • 解读CUDA Compiler Driver NVCC - Ch.3

    前言 上一篇文章简单了介绍了nvcc预定义的宏 以及支持的编译阶段 对应的输入文件后缀和输出文件的默认名 本篇文章了解CUDA源文件编译的整个workflow Overview CUDA编译的工作原理如下 输入程序经过设备编译编译预处理 编
  • HTTP的报文格式、GET和POST格式解析

    TTP报文是面向文本的 报文中的每一个字段都是一些ASCII码串 各个字段的长度是不确定的 HTTP有两类报文 请求报文和响应报文 请求报文 一个HTTP请求报文由请求行 request line 请求头部 header 空行和请求数据4个
  • JSON的下划线转驼峰,驼峰转下划线

    由于遇到了奇葩甲方 需要将数据格式转成下划线的格式 但是我们项目都是按照标准驼峰格式 所以写了个工具类来转换 不仅仅限于驼峰和下划线 根据需要传入 有没有大佬把这个递归改成迭代的 使用到的依赖 fastjon google的guava工具包
  • QT中代码设计和.ui文件设计的区别

    在面试中很多面试官经常会问到 ui和代码设计的区别 在网上一搜发现几乎没有人去解答这个问题 首先我们看一下一个简单的deamon 分别是代码实现和 ui实现 代码版 ui文件实现版 通过以上两种实现方式 不难发现 代码上的实现能够更精细 u
  • Navicat安装教程

    1 软件下载地址 点击下载 2 首先将下载后的文件解压到本地 3 右键选择以管理员身份运行navicat 15 0 64bit exe 4 然后点击下一步按钮 5 勾选我同意 然后点击下一步按钮 6 选择指定的安装目录 然后点击下一步按钮
  • micropython-SPI通讯

    micropython SPI通讯 1 什么是SPI 2 SPI通讯原理 3 Micropython中的SPI 4 ZTMR测试SPI 1 ZTMR中SPI引脚 2 ZTMRSPI自测 2 SPI 2板之间通讯测试 1 什么是SPI SPI
  • malloc底层原理实现

    使用过c语言的都知道malloc是一个动态分配内存的函数 还可以通过free释放内存空间 如果我们想分析一下malloc的源码 这其实不是一会就能看懂的 但是我们可以讨论一下malloc的简单实现 在这之前 我们先来看一下虚拟内存空间 虚拟