malloc()在哪里分配内存?是进程虚拟地址空间的数据段还是堆段?

2024-03-11

自从我被介绍到C,有人告诉我,在C动态内存分配是使用中的函数完成的malloc家庭。我还了解到,使用动态分配内存malloc分配在进程的堆部分。

各种操作系统教科书都这么说malloc涉及系统调用(虽然并不总是但有时)来将堆上的结构分配给进程。现在假设malloc返回指向堆上分配的字节块的指针,为什么它需要系统调用。函数的激活记录放置在进程的堆栈部分中,并且由于“堆栈部分”已经是进程虚拟地址空间的一部分,所以激活记录的压入和弹出、堆栈指针的操作,只需从虚拟地址空间的最高可能地址。它甚至不需要系统调用。

现在基于同样的理由,由于“堆部分”也是进程虚拟地址空间的一部分,为什么需要系统调用来在该部分中分配字节块。例行公事就像malloc可以自行处理“空闲”列表和“已分配”列表。它需要知道的只是“数据部分”的结尾。某些文本说系统调用对于“将内存附加到进程以进行动态内存分配”是必要的,但是如果malloc在“堆部分”分配内存为什么在过程中需要将内存附加到进程malloc?可以简单地取自过程中已经一部分的部分。

在阅读 Kernighan 和 Ritchie 所著的《C 编程语言》[2e] 时,我发现了他们对malloc函数[第 8.7 节第 185-189 页]。作者说:

malloc根据需要调用操作系统获取更多内存。

这就是操作系统文本所说的,但与我上面的想法相反(如果malloc在堆上分配空间)。

由于向系统请求内存是一个相对昂贵的操作,因此作者不会在每次调用时都这样做malloc,所以他们创建了一个函数morecore其要求至少NALLOC单位;这个较大的块根据需要被切碎。基本的空闲列表管理是通过free.

但问题是作者使用sbrk()向操作系统请求内存morecore。现在维基百科说:

brk and sbrk是 Unix 和类 Unix 操作系统中使用的基本内存管理系统调用,用于控制分配给数据段的过程。

Where

数据段(通常表示为 .data)是目标文件或程序的相应地址空间的一部分,其中包含初始化的静态变量,即全局变量和静态局部变量。

我猜这不是“堆部分”。 [数据部分是上图中从下数第二部分,而堆是从下数第三部分。]


我完全困惑了。我想知道到底发生了什么以及这两个概念如何正确?请通过将分散的碎片连接在一起来帮助我理解这个概念......


在您的图表中,标记为“数据”的部分更准确地称为“静态数据”;当进程启动时,编译器会为所有全局变量预先分配该内存。

那个堆malloc()use 是进程数据段的其余部分。最初在进程中分配给它的内存非常少。如果malloc()需要更多内存,它可以使用sbrk()扩展数据段的大小,或者可以使用mmap()在地址空间的其他地方创建额外的内存段。

为什么malloc()需要这样做吗?为什么不简单地让整个地址空间可供它使用呢?这有历史和现实的原因。

历史原因是早期的计算机没有虚拟内存。当在进程之间切换时,分配给进程的所有内存都会批量交换到磁盘。因此,仅分配实际需要的内存页非常重要。

实际原因是这对于检测各种错误很有用。如果您因取消引用未初始化的指针而遇到分段冲突错误,那么您已经从中受益。进程的大部分虚拟地址空间未分配给该进程,这使得未初始化的指针可能指向不可用的内存,并且在尝试使用它时会出现错误。

堆(向上增长)和堆栈(向下增长)之间还存在未分配的间隙。这用于检测堆栈溢出——当堆栈尝试使用该间隙中的内存时,它会收到一个错误,该错误会转换为堆栈溢出信号。

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

malloc()在哪里分配内存?是进程虚拟地址空间的数据段还是堆段? 的相关文章

  • 使用 CLion 进行 OpenCV Windows 设置

    我想在 Windows 上为 CLion IDE 设置 OpenCV 我尝试使用 OpenCV 3 1 和 2 4 得到相同的结果 我有 Windows 10 64 位 CLion 使用 cygwin 环境 到目前为止我做了什么 1 从Op
  • 多个源的 makefile

    在学习 make 文件时 我试图为多个源目录编写一个 make 文件 似乎我在某个地方错了 这是我的代码结构 directory common fun2 c inc fun h src fun1 c main c 这是我的生成文件 CC c
  • 将 new 与 decltype 一起使用

    T t T is an implementation detail t new T want to avoid naming T to allow for flexibility t new decltype t error cannot
  • Poco c++Net:Http 从响应中获取标头

    我使用 POCO C Net 库进行 http 我想尝试制定持久缓存策略 首先 我认为我需要从缓存标头中获取过期时间 并与缓存值进行交叉检查 如果我错了 请告诉我 那么我如何从中提取缓存头httpResponse 我已经看到你可以用 Jav
  • 在 OnModelCreating 期间设置列名称

    Issue 我目前正在尝试通过设置的属性为我的表及其列添加前缀 我正在使用实体框架核心 我已经正确地为表名添加了前缀 但我似乎无法弄清楚列的前缀 我有一种感觉 我需要使用反射 我已经留下了我的 可能很糟糕的 反思尝试 有人有办法在实体中设置
  • 在现代 C++ 中,临时生命周期延长何时有用?

    在 C 中 您可以将函数的返回值 返回值 而不是引用 绑定到 const 引用 并且代码仍然有效 因为该临时对象的生命周期将延长到作用域末尾 例如 std string get string return abc void f const
  • 将完整模板参数值映射到原始类型

    我想将数字映射到类型 在这个例子中 我将创建一个函数 将 sizeof 结果映射到有符号的原始类型 我想知道是否有更好的方法来完成我在现代 C 中所做的事情 即采用模板化值并将其转换为类型 现在 这可以将大小转换为已知类型 但我似乎无法在标
  • CSharpRepl emacs 集成?

    我碰巧知道莫诺CSharpRepl http www mono project com CsharpRepl 是否有 emacs csharp 模式使用它在一个窗口中运行 REPL 并像 python 模式一样在另一个窗口中编译 运行 C
  • 一元 +/- 运算符如何可能导致“-a”或“+a”中的整数提升,“a”是算术数据类型常量/变量?

    这句看似微不足道的台词摘自我的迈克 巴纳汉和布雷迪的 C 书 第 2 8 8 2 节 http publications gbdirect co uk c book chapter2 expressions and arithmetic h
  • C# 开源 NMEA 解析器 [已关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找 C 开源 NMEA 解析器 嗯 我自己也不熟悉 但是一些快速搜索显示了一个代码项目 htt
  • 获取 boost Spirit 语法中的当前行

    我正在尝试使用 boostspirit 获取正在解析的文件的当前行 我创建了一个语法类和结构来解析我的命令 我还想跟踪在哪一行找到命令并将其解析到我的结构中 我将 istream 文件迭代器包装在 multi pass 迭代器中 然后将其包
  • 增强精神、递归和堆栈溢出

    为什么下面的代码在运行时崩溃 它会给出堆栈溢出错误 include
  • UI 函数在快速事件完成之前触发

    我有一个停靠在 Silverlight 应用程序中的 Web 浏览器框架 有时会在其上弹出全窗口 XAML Silverlight UI 元素 我已经或多或少修复了一个老问题 即 Web 框架的内容似乎与 Silverlight 内容不能很
  • 使用 C# 和 wpf 创建类似 Dock 的应用程序

    我需要创建一个与我们购买笔记本电脑时获得的应用程序类似的应用程序 仅当鼠标指针到达窗口顶部时它才可见 那么我怎样才能使用 C 4 0 来做到这一点呢 http www notebookcheck net uploads pics win2
  • C#6 中的长字符串插值行

    我发现 虽然字符串插值在应用于现有代码库的字符串 Format 调用时非常好 但考虑到通常首选的列限制 字符串对于单行来说很快就会变得太长 特别是当被插值的表达式很复杂时 使用格式字符串 您将获得一个可以拆分为多行的变量列表 var str
  • 使用具有抗锯齿功能的 C# 更改抗锯齿图像的背景颜色

    我有一个图像需要更改背景颜色 例如 将下面示例图像的背景更改为蓝色 然而 图像是抗锯齿的 所以我不能简单地用不同的颜色替换背景颜色 我尝试过的一种方法是创建第二个图像 仅作为背景 并更改其颜色并将两个图像合并为一个图像 但是这不起作用 因为
  • Linux mremap 不释放旧映射?

    我需要一种方法将页面从一个虚拟地址范围复制到另一个虚拟地址范围 而无需实际复制数据 范围很大 延迟很重要 mremap 可以做到这一点 但问题是它也会删除旧的映射 由于我需要在多线程环境中执行此操作 因此我需要旧映射能够同时使用 因此稍后当
  • 从浏览器访问本地文件?

    您好 我想从浏览器访问系统的本地文件 由于涉及大量安全检查 是否可以通过某种方式实现这一目标 或使用 ActiveX 或 Java Applet 的任何其他工作环境 请帮帮我 要通过浏览器访问本地文件 您可以使用签名的 Java Apple
  • 在 OpenGL 中渲染纹理 1 到 1

    所以我想做的是使用 OpenGL 和 C 将纹理渲染到平面上 作为显示图像的一种方式 但是我需要确保在渲染纹理时没有对纹理进行任何处理 抗锯齿 插值 平滑 模糊等 这是 OpenGL 处理渲染纹理的默认方式吗 或者是否需要设置一些标志才能禁
  • 选择查询不适用于使用Parameters.AddWithValue 的参数

    C 中的以下查询不起作用 但我看不出问题所在 string Getquery select from user tbl where emp id emp id and birthdate birthdate cmdR Parameters

随机推荐