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 从请求到帧完成过程中,三种内存分配机制的典型协同关系:
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 实时监控虚拟地址空间变化,快速定位泄漏源。