malloc函数内存分配原理
malloc 是一个库函数,在<stdlib.h> 头文件中,是在程序的运行时库(Runtime Library)中实现的。这个函数主要用于在程序运行期间动态地分配内存。当在 C 语言程序中使用 malloc 时,实际上是在调用运行时库提供的一个函数,该函数会尝试从进程可用的内存池中分配一块大小适合的内存区域,并返回一个指向这块内存的指针。
malloc分配内存的原理:
1. 初始化
第一次调用 malloc 时,它会初始化一个内存池。这个内存池通常是通过向操作系统请求一块连续的内存区域来创建的。在 Unix-like 系统中,这通常通过 sbrk 系统调用来实现;而在 Windows 中,则可能通过 VirtualAlloc API 来实现。(如果分配的内存比较大,则可能会用mmap方式)
2. 内存池管理
malloc 维护一个内存池,内存池中包含已经分配出去的内存块以及空闲的内存块。通常,malloc 使用某种数据结构(如链表、二叉树或其他高效的数据结构)来跟踪这些内存块的状态(已分配/空闲)和大小。
3. 分配内存
当程序调用 malloc(size_t size) 请求分配内存时,malloc 需要在内存池中找到一个足够大的空闲块来满足请求。如果内存池中有足够的连续空闲空间,malloc 会从这个空闲块中分割出一块大小为 size 的内存,并返回一个指向这块内存的指针。
4. 内存对齐
malloc 会确保返回的内存地址是按照平台要求对齐的,比如在 x86 架构中,内存地址通常需要对齐到 8 字节或 16 字节边界,以优化内存访问性能。(不是所有平台都是这样)
5. 扩展内存池
如果内存池中的空闲块不足以满足新的请求,malloc 会尝试扩展内存池。这通常通过再次调用 sbrk 或 mmap 来实现,从操作系统获取更多的内存。新增的内存会被添加到内存池中,并可用于后续的内存分配请求。
6. 内存碎片处理
在多次分配和释放内存之后,内存池中可能会出现大量的小块空闲内存,这些小块之间不连续,导致内存碎片。malloc 可能会尝试合并相邻的小块空闲内存,使其成为一个较大的空闲块,从而减少内存碎片。
7. 释放内存
当程序不再需要某块内存时,应通过调用 free 函数来释放它。free 会将这块内存标记为空闲,并可能尝试与相邻的空闲块进行合并,以减少内存碎片。
8. 特殊情况处理
如果 malloc 发现无法从操作系统获取更多的内存来满足请求,它会返回 NULL,表示内存分配失败。
malloc分配的内存是虚拟内存还是物理内存?
malloc 分配的内存通常是虚拟内存。这是因为现代操作系统使用了虚拟内存机制,将进程的地址空间与实际物理内存区分开来。
既然是虚拟内存,那么分配的虚拟内存会和物理内存进行映射吗?
malloc 分配内存后,并不会立即为新分配的内存区域映射物理内存。相反,操作系统通常采用一种叫做“延迟分配”或“按需分页”(demand paging)的技术。这意味着在新分配的内存块中,只有当程序试图访问其中的数据时,才会触发一个分页错误(page fault),此时操作系统才会实际分配物理内存给这个虚拟地址,并建立虚拟地址到物理地址的映射。
这种策略有几个好处:
1.节省资源:如果分配的内存没有立即使用,那么就没有必要浪费物理内存。
2.提高效率:只有当内存真正被使用时才分配,可以避免不必要的内存分配和管理开销。
3.内存复用:操作系统可以复用未被实际使用的虚拟内存地址空间,直到它们被访问为止。
所以,malloc 分配的内存块在初始状态下一般是未映射到任何物理内存的。只有当程序开始读取或写入这部分内存时,操作系统才会分配物理内存并完成映射。这种机制使得内存管理更加灵活和高效。
原文地址:https://blog.csdn.net/shugenlee/article/details/142218722
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!