malloc 的原理?malloc 的底层实现?

目录

1. malloc 的基本原理

2. malloc 的底层实现

a. 内存分配算法

b. 内存管理函数

c. 合并和分割

d. 内存碎片化处理

3. 常见的 malloc 实现库

4.示例


malloc 的底层实现是一个复杂的内存管理过程,它通过不同的算法和系统调用高效地管理动态内存分配和释放。在现代系统中,malloc 实现已进行了大量优化,以提高性能和减少内存碎片化。

malloc 是 C 语言中的一个动态内存分配函数,用于从堆中分配指定大小的内存块。它的底层实现涉及操作系统的内存管理机制和用户态的内存管理库(如 glibcmalloc 实现)。下面是 malloc 的基本原理和底层实现的简要介绍:

1. malloc 的基本原理

  • 功能malloc 用于动态分配内存。它接收一个参数,表示需要分配的字节数,并返回一个指向已分配内存块的指针。如果分配失败(例如内存不足),它返回 NULL
  • 内存来源malloc 分配的内存来自进程的堆区(heap),堆区是进程的可增长区域,位于程序的已使用内存区和未使用内存区之间。

2. malloc 的底层实现

  • malloc 的实现因库和操作系统不同而略有差异,以下是常见实现方式的主要步骤:

a. 内存分配算法

  • 自由链表(Free List):管理未分配的内存块,以加快分配速度。空闲块按大小排序,并形成链表。
  • 首次适配(First-Fit):寻找第一个足够大的空闲块用于分配。
  • 最佳适配(Best-Fit):寻找最接近所需大小的空闲块,以减少碎片化。
  • 快速适配(Fast-Fit):通过缓存特定大小的空闲块来加速内存分配和回收。

b. 内存管理函数

  • brksbrk:这些系统调用用于增加或减少进程的堆空间。brk 设置堆的结束地址,sbrk 调整当前堆的大小。
  • mmap:用于分配大块内存或当 brk 的调整不够用时直接映射内存,通常用于分配大于一定阈值的块。

c. 合并和分割

  • 分割:当找到的空闲块比请求的内存大时,会将块分割为两部分,一部分用于满足请求,剩余部分继续作为空闲块。
  • 合并:当内存被释放时,若相邻的块也是空闲的,它们会被合并以减少碎片化。

d. 内存碎片化处理

  • 内碎片:指分配的内存块比请求的稍大,导致小块内存被浪费。常通过合并和重新分配减少。
  • 外碎片:指小的空闲块分布在内存中,无法满足较大内存请求。通过内存紧缩(如 mremap)减少外碎片。

3. 常见的 malloc 实现库

  • glibcmalloc:广泛用于 Linux 系统的 C 库实现,采用分离适配器机制,支持快速分配、延迟合并等优化。
  • jemalloctcmalloc:高级的内存分配库,优化了多线程环境下的性能和减少内存碎片的能力。

4.示例

#include <stdio.h>
#include <stdlib.h>  // 包含 malloc、free 函数

int main() {
    // 请求分配 10 个 int 类型大小的内存块
    int *arr = (int *)malloc(10 * sizeof(int));
    
    // 检查分配是否成功
    if (arr == NULL) {
        printf("Memory allocation failed\n");
        return 1;
    }

    // 使用分配的内存
    for (int i = 0; i < 10; i++) {
        arr[i] = i * i;
    }

    // 打印已分配内存中的数据
    for (int i = 0; i < 10; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    // 释放分配的内存
    free(arr);

    return 0;
}

分析该示例背后的 malloc 底层操作

  1. 请求内存:程序调用 malloc 请求 10 个 int 大小的连续内存块,总计 10 * sizeof(int) 字节(通常是 40 字节)。

  2. 内部操作

    • 寻找合适块malloc 从自由链表中查找一个合适的空闲块。如果找到足够大的块,它将返回该块的起始地址。
    • 分割:如果找到的空闲块大于请求的内存大小,malloc 可能会将该块分割成两部分:一部分用于满足请求,另一部分留作空闲。
    • 系统调用:如果堆上没有足够大的空闲块,malloc 可能会通过 brkmmap 向操作系统请求更多内存。
  3. 内存使用:程序在已分配的内存中写入数据,arr[i] = i * i;。分配的内存在使用后必须被释放,否则会导致内存泄漏。

  4. 释放内存

    • 调用 free(arr) 释放内存,free 会将内存块标记为可用,并尝试与相邻空闲块合并以减少碎片化。
    • 释放的内存不会立即返回给操作系统,而是保留在堆上供后续的 malloc 请求使用。

模拟底层操作的简单示例

为更直观地理解 malloc 的内部分配和释放,假设堆管理如下所示:

Heap Before Allocation:
-----------------------------------
| Free Block | Used Block | Free Block |
|    100B    |    50B     |   200B    |
-----------------------------------

After malloc(40B):
-----------------------------------
| Free Block | Used Block | Used Block | Free Block |
|    100B    |    50B     |    40B     |   160B    |
-----------------------------------

After free(40B):
-----------------------------------
| Free Block | Used Block | Free Block | Free Block |
|    100B    |    50B     |    40B     |   160B    |
-----------------------------------

After Coalescing:
-----------------------------------
| Free Block | Used Block | Free Block |
|   140B     |    50B     |   160B    |
-----------------------------------

这个例子展示了 malloc 的分配过程、内存块的管理和 free 后的合并操作,有助于理解 malloc 如何高效管理内存。

  • 12
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值