malloc 的详细工作原理是什么?

how does malloc work in details?

我正在尝试查找有关 malloc 函数的一些有用信息。 当我调用这个函数时,它会动态分配内存。它 returns 指向已分配内存开头的指针(例如地址)。 问题:

既然您使用的是 malloc,我们可以假设您使用的是 C 语言吗? 如果是这样,您将结果分配给一个指针变量,然后您可以通过引用该变量来访问内存。你真的不知道这是如何在汇编中实现的。这取决于您使用的 CPU。 malloc return 0 如果失败。由于通常 NULL 被定义为 0,因此您可以测试 NULL。您不关心 malloc 如何跟踪空闲内存。如果您确实需要此信息,您应该查看 glibc/malloc 中的源代码,可在网上找到

char * c = malloc(10);   // allocate 10 bytes
if (c == NULL)
   // handle error case
else
   *c = 'a'  // write a in the first character on the block

Q3 通常管理堆的方式是通过链表。在最简单的情况下,malloc 函数保留指向堆中第一个 free-space 块的指针,每个 free-space 块都有一个指向下一个空闲 space 的 header块在堆中。所以堆是 in-effect self-defining 就知道什么没有被占用(以及由此推断什么被占用)而言;这最大限度地减少了管理堆所需的开销 RAM 量。

当通过 malloc 调用需要新的 space 时,通过遍历链表找到足够大的 free-space 块。找到的 free-space 块被提供给 malloc 调用者(带有一个小的隐藏 header),如果需要,一个较小的 free-space 块被插入到链表中,其中包含任何残差 space 在原始空闲 space 块和 malloc 调用要求的内存量之间。

当一个堆块被应用程序释放时,它的块只是用linked-listheader格式化,并添加到链表中,通常有一些额外的逻辑来组合连续的free-space 块合并为一个更大的 free-space 块。

调试版本的 malloc 通常会做更多的事情,包括也保留 linked-list 分配的区域,"guard zones" 在分配的堆区域周围帮助检测内存溢出等。这些占用额外的堆space(就应用程序可用 space 而言,使堆有效变小),但在调试时非常有用。

Q2 NULL 指针实际上只是一个零,如果使用它会尝试访问从 RAM 的位置 0 开始的内存,这几乎总是 OS 的保留内存。这是大量内存违规中止的原因,所有这些都是由于程序员缺乏对分配内存的函数的 NULL returns 错误检查造成的)。

因为 non-OS 应用程序访问内存位置 0 从来都不是我们想要的,所以大多数硬件都会中止 non-OS 软件访问位置 0 的任何尝试。即使使用页面映射使得应用程序内存 space(包括位置 0)永远不会映射到实际 RAM 位置 0,因为 NULL 始终为零,大多数 CPU 仍然会中止访问位置 0 的尝试,假设这是通过包含 NULL 的指针进行访问。

鉴于您的 RISC 处理器,您将需要阅读其文档以了解它如何处理访问内存位置 0 的尝试。

Q1 有许多 high-level 语言方法可以使用分配的内存,主要是通过指针、字符串和数组。

就汇编语言和硬件本身而言,分配的堆块地址只是被放入一个用于内存间接寻址的寄存器中。您将需要了解 RISC 处理器是如何处理它的。但是,如果您使用 C 或 C++ 或此类更高级的语言,则无需担心寄存器;编译器会处理所有这些。