内存泄漏系列专题分析之五:使用malloc_debug定位C/C++ native heap内存泄露
【关注我后续持续新增专题博文谢谢】上一篇我们讲了内存泄漏系列专题分析之四Android malloc_debug工具在Camera领域使用中预览卡死的瓶颈限制问题和二次改造这一篇我们开始讲内存泄漏系列专题分析之五使用malloc_debug定位C/C native heap内存泄露目录一、Malloc Debug配置说明1.1常见配置1.2malloc debug log日志1.3native_heapdump_viewer.py 使用二、使用Malloc Debug2.1打开Malloc Debug2.2分析原始dump文件2.3native_heapdump_viewer.py 格式化2.4解析调用栈2.5分析调用栈对应代码2.6总结本文主要介绍使用Google原生Android自带的malloc debug帮助定位C/C native heap内存泄露的方法。一、Malloc Debug配置说明1.1常见配置front_guard[SIZE_BYTES] 每次调用 malloc ,都在分配的区域之前填充 SIZE_BYTES ,填充内容为 0xaarear_guard[SIZE_BYTES] 每次调用 malloc ,都在指向内存的最后填充 SIZE_BYTES ,填充内容为 0xbbguard[SIZE_BYTES] 这个选项包含了 front_guard 和 rear_guard 。在指向内存的前后连 续 SIZE_BYTES 分别填充 0xaa 和 0xbbbacktrace[MAX_FRAMES] 这 个 optipn s 会 将 内存分配的速度减慢一个数量级 ,MAX_FRAMES 最大 值 256 默认值 16 。 每次在调用 malloc 时 , malloc debug 都会记录 malloc 的调用栈 (trace).栈的最大深度为 MAX_FRAMES , MAX_FRAMES 越大 , 对 malloc 的性能影响越大 , 也就越慢。当进程收到信号 SIGRTMAX - 17 Android 通常该信号值为 47 时, 会触发 malloc debug 的 dump heap trace 功能。 默认 dump 路径在 /data/local/tmp/ backtrace_heap.PID.txt 。给进程发信号通过 kill -s 47 PID , 进程收 到信号后并不会马上 dump backtrace , 而是会等到下次调用 malloc 或者 free 时 才会触发。所以如果发送信号后没有产生 trace 文件,请继续针对调试的进程做 测试。执行 kill -s 47 PID 之后,系统开始进行等待用户执行 malloc 操作。 举例 setprop libc.debug.malloc.options backtrace5 得到的 dump 文件为 $pid.txt 结尾backtrace_enable_on_signal[MAX_FRAMES] :使能这个选项 , 通过给进程发送信号 45 , 可以动态开启和关闭 backtrace 功能 。backtrace_dump_on_exit进程退出后自动 dump trace 文件,得到的 dump 文件为 $pid.exit.txt 结尾backtrace_dump_prefixtrace dump 的路径 , 如果需要放置其他目录 , 如 /sdcard/heap, 则 dump 的文件路 径为 /sdcard/heap.$PID.txtleak_track程序结束后,如果有未 free 的指针, logcat 中会打印出来12-19 14:54:32.583 7971 7971 E malloc_debug: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 12-19 14:55:02.585 7971 7971 E malloc_debug: androidtest leaked block of size 3072 at 0x736e78f030 (leak 1 of 7) // 内存泄露的 log ,直到程序退出未释放的内存 12-19 14:55:02.585 7971 7971 E malloc_debug: Backtrace at time of allocation: 12-19 14:55:02.585 7971 7971 E malloc_debug: #00 pc 00000000000152b0 /apex/com.android.runtime/lib64/libc_malloc_debug.so (debug_calloc432) 12-19 14:55:02.585 7971 7971 E malloc_debug: #01 pc 000000000000114c /system/bin/androidtest // 通过 addr2line -e symbols/system/bin/androidtest 000000000000114c 可以得到具体是哪一个指针未释放内存。 12-19 14:55:02.585 7971 7971 E malloc_debug: #02 pc 000000000007d86c /apex/com.android.runtime/lib64/bionic/libc.so (__libc_init108) 12-19 14:55:02.585 7971 7971 E malloc_debug: #03 pc 000000000000104c /system/bin/androidtest 12-19 14:55:02.585 7971 7971 E malloc_debug: #04 pc 00000000000533f4 /apex/com.android.runtime/bin/linker64 12-19 14:55:02.585 7971 7971 E malloc_debug: androidtest leaked block of size 88 at 0x736e631030 (leak 2 of 7)record_allocs[TOTAL_ENTRIES]该选项很占内存 , 建议不开启。对进程中使用 malloc, calloc, realloc 的地方进行记录,打印的格式如下Threadid: action pointer size 471: malloc 0x72e00330c0 6 471: realloc 0x72e0005220 0x72e00330c0 12 471: free 0x72e012fcc0 471: free 0x72e0005220 471: malloc 0x72e01ade40 56 471: malloc 0x72e00330c0 6 注意,最大记录 8,000,000 条1.2malloc debug log日志verbose 打开 malloc debug 更多 log ,类似08-16 15:54:16.060 26947 26947 I libc : /system/bin/app_process64: malloc debug enabled09-10 01:03:50.070 557 557 I malloc_debug: /system/bin/audioserver: Run: kill -47 557 to dump the backtrace.1.3native_heapdump_viewer.py 使用该工具可以将 dump trace 文件通过符号表得到当前 未释放内存的指针在代 码中的行号 。准确性依赖 trace 保存栈的最大深度。所以最好有两份该文件,分 别是不同占用内存时 dump 得到的。对比查看哪个指针嫌疑最大,缩小范围继 续排查。其中 symbols 路径要正确二、使用Malloc Debug本文主要介绍使用Google原生Android自带的malloc debug帮助定位C/C native heap内存泄露的方法。2.1打开Malloc Debug针对android.hardware.graphics.composer2.1-service打开malloc debug#!/bin/bash# 需要重启上层让 property 生效stop# 指定 debug 参数。可以默认这样写更多选项参考# bionic/libc/malloc_debug/README.mdsetproplibc.debug.malloc.optionsbacktrace16 guard8 fill_on_free16# 指定要开malloc debug的进程setproplibc.debug.malloc.programandroid.hardware.graphics.composer2.1-service# 进程重启用libc_deubg.so替换原来的libc.SO库mallocDebug代码生效kill -9 $(pidof android.hardware.graphics.composer2.1-service)start# 需要关闭SELinux和目录读写权限setenforce 0chmod 777 /data/local/tmp# 触发Malloc Debug dump默认会生成如下dump文件# /data/local/tmp/backtrace\_heap.**PID**.txtkill -47 $(pidof android.hardware.graphics.composer2.1-service)2.2分析原始dump文件原始dump展现形式:1. 第一部分主要包含分配内存的大小分配的次数分配内存的函数调用栈地址。相同的调用栈用一行表示。z 0 sz 242952 num 1 bt 776cd9667c 776cd964a8 776d7977bc 776a16e384 776a16e6d0 776a16e4d8 776a1701bc 776a16fff0 776a188b48 776a188a0c 776a175394 776a179038 7769881260 7769878458 7769862208 776985ce4c z 0 sz 163840 num 1 bt 776cd9667c 776cd964a8 776a1937b4 776a1913d4 776a198cf8 776a199128 776a16fa80 776a1703cc 776a170328 776a188a30 776a175394 776a179038 7769881260 7769878458 7769862208 776985ce4c z 0 sz 163840 num 1 bt 776cd9667c 776cd964a8 776a19362c 776a1912e0 776a16f164 776a16e394 776a16e6d0 776a16e4d8 776a1701bc 776a16fff0 776a188b48 776a188a0c 776a175394 776a179038 7769881260 77698784582. 第二部分包含进程二进制代码在进程空间内加载的地址。配合第一部分可以确认分配函数的调用栈。7765e92000-7765e9d000 --xp 00009000 fd:08 3329 /vendor/lib64/hw/gralloc.mt6885.so 7765e9d000-7765e9e000 rw-p 00014000 fd:08 3329 /vendor/lib64/hw/gralloc.mt6885.so 7765e9e000-7765e9f000 r--p 00015000 fd:08 3329 /vendor/lib64/hw/gralloc.mt6885.so 7765e9f000-7765ea0000 rw-p 00000000 00:00 0 [anon:.bss] 7765ec4000-7765ed9000 r--p 00000000 fd:07 3965 /system/lib64/libEGL.so 7765ed9000-7765ef1000 --xp 00015000 fd:07 3965 /system/lib64/libEGL.so 7765ef1000-7765ef2000 rw-p 0002d000 fd:07 3965 /system/lib64/libEGL.so 7765ef2000-7765ef7000 r--p 0002e000 fd:07 3965 /system/lib64/libEGL.so2.3native_heapdump_viewer.py 格式化原始的dump文件可读性差可以使用 development/scripts/native_heapdump_viewer.py 格式化转换为树状结构转换后的dump文件会有很多分配内存的堆栈信息。这里只提取了内存泄漏最严重的一个堆栈为了方便查看只截取了每行的前面部分:BYTES %TOTAL %PARENT COUNT ADDR LIBRARY FUNCTION LOCATION 0 0.00% 0.00% 0 APP 181538320 100.00% 100.00% 566960 ZYGOTE 152077336 83.77% 83.77% 391966 776d8aa2cc /system/lib64/vndk-29/android.hardware.graphics.co 152077336 83.77% 100.00% 391966 776d8a9628 /system/lib64/vndk-29/android.hardware.graphics. 152077336 83.77% 100.00% 391966 776ba1a598 /vendor/lib64/hw/android.hardware.graphics.com 152077336 83.77% 100.00% 391966 776ba1d0b4 /vendor/lib64/hw/android.hardware.graphics.c 147506972 81.25% 96.99% 380182 776ba1e4f0 /vendor/lib64/hw/android.hardware.graphics 147506972 81.25% 100.00% 380182 776ba1f654 /vendor/lib64/hw/android.hardware.graphi 147506972 81.25% 100.00% 380182 776ba17704 /vendor/lib64/hw/android.hardware.grap 147506972 81.25% 100.00% 380182 7769850744 /vendor/lib64/hw/hwcomposer.mt6885.s 147506048 81.25% 100.00% 380171 776988dfd8 /vendor/lib64/hw/hwcomposer.mt6885 147505960 81.25% 100.00% 380170 7769859c3c /vendor/lib64/hw/hwcomposer.mt68 147505960 81.25% 100.00% 380170 7769862134 /vendor/lib64/hw/hwcomposer.mt 147505960 81.25% 100.00% 380170 7769875bd0 /vendor/lib64/hw/hwcomposer. 147505960 81.25% 100.00% 380170 776a176bd8 /vendor/lib64/libdpframworks 147505960 81.25% 100.00% 380170 776d7977bc /system/lib64/vndk-sp-29 147505960 81.25% 100.00% 380170 776cd964a8 /system/lib64/libc_mal文件记录了当前进程所有使用malloc系列接口分配内存的操作每次还没有释放的分配计数为1是潜在的内存泄露。排在最前面的是持有内存最多的操作。可以看到composer进程中使用内存最多的是libdpframworks模块共使用内存147505960Kb还有380170次分配的内存没有释放在composer所有还没有释放的分配中占比81.25%。显然这个调用栈非常可疑。我们重点关注这一行147505960 81.25% 100.00% 380170 776a176bd8 /vendor/lib64/libdpframworks2.4解析调用栈查看调用栈我们容易知道分配内存的地方在如下的代码中147505960 81.25% 100.00% 380170 776a176bd8 /vendor/lib64/libdpframework.soDpAsyncBlitStream2::createJob(unsigned int, int) vendor/mediatek/proprietary/hardware/dpframework/common/stream/DpAsyncBlitStream2.cpp:85DP_STATUS_ENUM DpAsyncBlitStream2::createJob(uint32_t jobID, int32_t fence) { DP_STATUS_ENUM status; struct AsyncBlitJobPair *pJob; int32_t fenceFD, fenceFD2; //分配内存 pJob new struct AsyncBlitJobPair; if (pJob NULL) { DPLOGE(DpAsyncBlitStream2: cannot allocate job\n); return DP_STATUS_OUT_OF_MEMORY; } }2.5分析调用栈对应代码跟踪pJob的生命周期我们最终定位到内存泄露的位置DP_STATUS_ENUM DpAsyncBlitStream2::invalidate(struct timeval *endTime) { DP_STATUS_ENUM status; struct AsyncBlitJobPair *pJob; { ... pJob m_jobList.front(); } ... { AutoMutex lock(m_pJobMutex); m_jobList.erase(m_jobList.begin()); //从链表取出使用后忘记释放资源. 这里应该有delete delete pJob; }2.6总结使用Malloc Debug工具我们关心BYTES和%TOTAL两个指标。如果这两个指标一直偏大就标明可能存在内存泄露。【关注我后续持续新增专题博文谢谢】下一篇讲解内存泄漏系列专题分析之六高通camx 内存泄漏测试的未回收问题分析

相关新闻

MCP 接入后,桌面 Agent 如何秒变「万能插座」?3 个办公自动化案例实测

MCP 接入后,桌面 Agent 如何秒变「万能插座」?3 个办公自动化案例实测

从封闭系统到开放工作台 上周用 Python 脚本批量处理 Excel 时,发现要反复切换浏览器查数据、开 IDE 跑清洗、再用邮件客户端发结果——这种碎片化操作在办公场景太常见。直到把有道 Lobster 的 MCP(Multi-Channel Processor)模块接进来&…

2026/7/25 10:04:03 阅读更多 →
Reducer 是什么?多个节点如何安全更新状态

Reducer 是什么?多个节点如何安全更新状态

上一篇文章里,我们讨论了 Edge 和 Conditional Edge。 一个重要结论是: Edge 让流程可以分支,也可以回到前面的节点。 但一旦流程变复杂,就会遇到另一个问题: 多个节点如何安全更新同一份 State? 这就是 Re…

2026/7/24 6:54:45 阅读更多 →
计算机毕业设计之基于Spring Boot的洗衣店智能服务系统的设计与实现

计算机毕业设计之基于Spring Boot的洗衣店智能服务系统的设计与实现

随着人们生活水平的提高和生活节奏的加快,人们对衣物清洁的需求不断增加,传统的洗衣服务模式已难以满足现代消费者对便捷、高效、个性化服务的追求。因此,开发一套基于Spring Boot的洗衣店智能服务系统成为当务之急。该系统旨在通过信息化手段…

2026/7/25 7:05:05 阅读更多 →

最新新闻

大麦网自动抢票脚本终极实战指南:Python API直连技术深度解析

大麦网自动抢票脚本终极实战指南:Python API直连技术深度解析

大麦网自动抢票脚本终极实战指南:Python API直连技术深度解析 【免费下载链接】Automatic_ticket_purchase 大麦网抢票脚本 项目地址: https://gitcode.com/GitHub_Trending/au/Automatic_ticket_purchase 在热门演出票务秒光的时代,手动抢票成功…

2026/7/26 0:26:40 阅读更多 →
安卓手机上的专业级播放器,到底强在哪?

安卓手机上的专业级播放器,到底强在哪?

手机自带的播放器功能太基础,第三方播放器又广告满天飞?如果你在安卓平台上找一款真正"能打"的视频播放工具,XPlayer 值得放进你的候选清单。 XPlayer 是一款专注于安卓平台的专业级视频播放工具。 它的定位很明确:不做…

2026/7/26 0:26:40 阅读更多 →
java:Iterative Algorithms

java:Iterative Algorithms

项目结构:/*** encoding: utf-8* 版权所有 2026 ©涂聚文有限公司 * 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎* 描述:Iterative Algorithms* Author : geovindu,Geovin Du 涂聚文.* IDE : Intel…

2026/7/26 0:26:40 阅读更多 →
3分钟快速上手:GitHub中文插件完全指南

3分钟快速上手:GitHub中文插件完全指南

3分钟快速上手:GitHub中文插件完全指南 【免费下载链接】github-chinese GitHub 汉化插件,GitHub 中文化界面。 (GitHub Translation To Chinese) 项目地址: https://gitcode.com/gh_mirrors/gi/github-chinese 还在为GitHub全英文界面而烦恼吗&a…

2026/7/26 0:26:40 阅读更多 →
ThinkPad风扇控制革命:TPFanCtrl2让你的笔记本静如处子,动如脱兔

ThinkPad风扇控制革命:TPFanCtrl2让你的笔记本静如处子,动如脱兔

ThinkPad风扇控制革命:TPFanCtrl2让你的笔记本静如处子,动如脱兔 【免费下载链接】TPFanCtrl2 ThinkPad Fan Control 2 (Dual Fan) for Windows 10 and 11 项目地址: https://gitcode.com/gh_mirrors/tp/TPFanCtrl2 作为一名ThinkPad用户&#xf…

2026/7/26 0:25:40 阅读更多 →
Windows 11优化终极指南:3步让你的系统重获流畅体验

Windows 11优化终极指南:3步让你的系统重获流畅体验

Windows 11优化终极指南:3步让你的系统重获流畅体验 【免费下载链接】Win11Debloat A simple, lightweight PowerShell script that allows you to remove pre-installed apps, disable telemetry, as well as perform various other changes to declutter and cust…

2026/7/26 0:25:40 阅读更多 →

日新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/26 0:00:31 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/26 0:00:31 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/26 0:00:31 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/26 0:00:31 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/26 0:00:31 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/26 0:00:31 阅读更多 →

月新闻