malloc是如何详细工作的



我试图找到一些关于malloc函数的有用信息。当我调用这个函数时,它会动态地分配内存。它将指针(例如地址)返回到所分配的存储器的开头。问题:

  • 如何使用返回的地址来读取/写入分配的内存块(使用间接寻址寄存器还是如何?)

  • 如果无法分配内存块,则返回NULL。在硬件方面什么是NULL?

  • 为了在堆中分配内存,我们需要知道哪些内存部分被占用了。这些信息(关于占用的存储器)存储在哪里(例如,如果我们使用小型risc微控制器)?

Q3管理堆的常用方法是通过链表。在最简单的情况下,malloc函数保留一个指向堆中第一个可用空间块的指针,每个可用空间块都有一个指向堆栈中下一个可用空间区块的头。因此,堆实际上是自我定义的,即知道什么没有被占用(以及通过推断什么因此被占用);这样可以最大限度地减少管理堆所需的RAM开销。

当通过malloc调用需要新空间时,通过遍历链表可以找到足够大的可用空间块。找到的可用空间块被提供给malloc调用方(带有一个小的隐藏头),如果需要,将一个较小的可用空间插入到链表中,在原始可用空间块和malloc请求的内存量之间留有任何剩余空间。

当应用程序释放堆块时,它的块只使用链表头进行格式化,并添加到链表中,通常使用一些额外的逻辑将连续的可用空间块组合成一个更大的可用空间区块。

malloc的调试版本通常做得更多,包括保留已分配区域的链表,在已分配的堆区域周围设置"保护区"以帮助检测内存溢出等。这些占用了额外的堆空间(使堆在应用程序的可用空间方面实际上更小),但在调试时非常有用。

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

因为非操作系统应用程序访问内存位置0从来都不是想要的,所以大多数硬件都会中止非操作系统软件访问位置0的任何尝试。即使页面映射使得应用程序内存空间(包括位置0)从未映射到实际RAM位置0,由于NULL始终为零,大多数CPU仍然会中止访问位置0的尝试,假设这是通过包含NULL的指针进行的访问。

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

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

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

既然你在使用malloc,我们能假设你在使用C吗?如果是这样,则将结果分配给指针变量,然后可以通过引用该变量来访问内存。您并不真正知道这是如何在程序集中实现的。这取决于您使用的CPU。如果失败,malloc将返回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

相关内容

  • 没有找到相关文章