3. 内存分配与释放机制:malloc/free、new/delete、mmap/munmap 在 HAL 中的典型用法

Camera HAL 运行在资源受限的多媒体域,内存分配与释放的路径直接影响帧率、功耗和稳定性。本章聚焦三种核心内存管理接口在 HAL 层的典型用法、适用场景及常见陷阱。

3.1 三种分配机制对比

接口 分配来源 典型用途 释放方式 HAL 中常见问题
malloc / free 用户态堆 (Heap) 元数据、控制结构、小尺寸临时 buffer free() 忘记释放导致堆内存泄漏
new / delete 用户态堆 (Heap) C++ 对象、类实例、STL 容器 delete new/delete 不配对、数组 delete 遗漏 []
mmap / munmap 虚拟地址空间 / 物理连续内存 大块帧 buffer、ION/DMA-BUF 映射、共享内存 munmap() 映射未解绑、VMA 泄漏、page table 膨胀
关键原则:HAL 中超过 80% 的内存泄漏源于 mmap 映射未及时 munmap,以及 new 分配的 C++ 对象在异常路径中未执行 delete。

3.2 malloc/free:元数据与临时 buffer

在 Camera HAL 中,malloc/free 主要用于分配 metadata、request 描述符、统计信息结构体 等小尺寸对象。这些对象生命周期短,分配频繁,容易成为泄漏重灾区。

// 典型错误:异常路径未释放
camera_metadata_t *meta = (camera_metadata_t *)malloc(sizeof(camera_metadata_t));
if (!meta) return -ENOMEM;

int ret = process_metadata(meta);
if (ret < 0) {
    // 忘记 free(meta) → 泄漏
    return ret;
}
free(meta);
最佳实践:在 HAL 中建议使用 ScopedMalloc 或 RAII 包装器,确保所有退出路径都执行 free()。对于频繁分配/释放的场景,考虑使用内存池(Memory Pool)减少碎片。

3.3 new/delete:C++ 对象生命周期管理

现代 Camera HAL 大量使用 C++ 类(如 CameraDevice、Stream、RequestThread)。new/delete 的不配对使用是 C++ 泄漏的主要来源。

// 错误示例:数组 delete 遗漏 []
CameraStream *streams = new CameraStream[10];
// ... 使用 streams ...
delete streams;          // 错误!只释放了第一个元素
delete[] streams;        // 正确

// 错误示例:异常路径未 delete
CameraDevice *dev = new CameraDevice();
if (dev->init() < 0) {
    return;              // 泄漏 dev
}
delete dev;
避坑提示:HAL 中 new 分配的对象如果被注册到回调或观察者列表中,必须在 delete 前先解除注册,否则后续回调会访问已释放内存(Use-After-Free)。

3.4 mmap/munmap:大块帧 buffer 与共享内存

mmap 是 Camera HAL 中最重要的内存映射机制,用于将 ION/DMA-BUF 物理内存映射到用户态虚拟地址空间。它直接决定帧数据的读写效率。

// HAL 中典型的 mmap 流程
int ion_fd = ion_alloc(..., &ion_handle);
void *vaddr = mmap(NULL, size, PROT_READ | PROT_WRITE,
                   MAP_SHARED, ion_fd, 0);
if (vaddr == MAP_FAILED) {
    close(ion_fd);
    return -ENOMEM;
}
// ... 使用 vaddr 填充帧数据 ...
munmap(vaddr, size);   // 必须配对
close(ion_fd);

mmap 泄漏的典型场景:

  • 映射未解绑:buffer 返回给驱动后,用户态映射未 munmap,导致 VMA 持续增长。
  • 异常路径遗漏:在帧处理中途发生错误,直接 return 跳过 munmap。
  • 多次 mmap 同一 fd:未检查是否已映射,重复映射导致虚拟地址空间耗尽。
性能指标:每帧 4K 分辨率(约 8MB)的 buffer,如果每帧泄漏一次 mmap,30fps 下 10 秒内虚拟地址空间增长约 2.4GB,直接导致 OOM 或系统 kill HAL 进程。

3.5 三种机制在 HAL 中的协同流程

下图展示 Camera HAL 从请求到帧完成过程中,三种内存分配机制的典型协同关系:

Camera HAL 内存分配协同流程 App 下发 Capture Request HAL 解析 Request malloc 分配 metadata new 创建 Stream 对象 ION 分配物理 buffer mmap 映射到用户态 ISP/HAL 填充帧数据 帧处理完成 munmap 解绑 buffer delete 释放 Stream 对象 free 释放 metadata

3.6 常见泄漏模式与检测方法

泄漏模式 涉及接口 检测手段 修复策略
异常路径未释放 malloc/free 静态分析、Code Review RAII 包装、goto cleanup 模式
new/delete 不配对 new/delete Valgrind、ASan 智能指针 std::unique_ptr
mmap 未 munmap mmap/munmap /proc/pid/maps、pmap 映射生命周期与 buffer 绑定
多次 mmap 同一 fd mmap VMA 计数监控 映射前检查是否已映射
实用工具:在 HAL 开发阶段,建议在关键分配/释放点添加日志,配合 dumpsys meminfo 和 cat /proc/pid/maps 实时监控虚拟地址空间变化,快速定位泄漏源。