内存泄露分析
背景
N项目超级夜景模式泄露内存,且泄露内存较大,大概每次19M
依赖
对内存有基本的知识了解。
对syscall有基本的了解和对调试工具strace的使用
分析过程
抓取相关信息
- 针对内存泄露抓取hal进程内存总体和分配情况,针对较大内存泄露,三次场景复现后对比前后抓取,因为抓取文件偏多,因此需要脚本抓取。在抓取前需要先确定进程pid
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| @echo off setlocal enabledelayedexpansion adb wait-for-device echo "#### test start ####" #timeout 120 #需要重新开机,并进行一次打开关闭camera操作,等120s #开始抓取内存分布 adb shell dumpsys meminfo | findstr camera >> before-supernight-leak.txt echo -------------------------- >> before-supernight-leak.txt adb shell dumpsys meminfo 26639 >> before-supernight-leak.txt echo -------------------------- >> before-supernight-leak.txt adb shell cat /proc/26639/maps >> before-supernight-leak.txt adb shell cat /proc/26639/smaps >> before-supernight-leak-smaps.txt #开始抓取syscall,打开到夜景模式复现三次 for /L %%i in (1,1,3) do ( echo 第 %%i / 3 次 adb shell input tap 347 1288 timeout 10
) #等20s再停止抓取syscall #等60s之后内存稳定再抓取一次内存分布 #timeout 60 adb shell dumpsys meminfo | findstr camera >> after-supernight-leak.txt echo -------------------------- >> after-supernight-leak.txt adb shell dumpsys meminfo 26639 >> after-supernight-leak.txt echo -------------------------- >> after-supernight-leak.txt adb shell cat /proc/26639/maps >> after-supernight-leak.txt
adb shell cat /proc/26639/smaps >> after-supernight-leak-smaps.txt
timeout 1
pause
|
- 我们需要通过是哪个系统调用进行的内存申请来确定相关线程和代码范围,因此在整个复现过程需要strace来抓取系统调用,需要抓取整个进程包括子线程并将输出重定向到指定文件
strace -o output.txt -T -tt -p 28979 -f
分析
- 进程内存大体对比分析
这是三次夜景拍照前后的对比,可以看出PSS,RSS, Native Heap均有50到60M左右的增长。
- 进程内存具体分配变化对比分析
内存分配的变化会有多处,但是针对泄露较大的,只需要对比MB级别的内存区域变化即可,KB的不需要关心。对比发现两处大小有规律性的内存变化,即0x842e9000开始的19M和0xa737d000开始的38M,因此确定三次泄露地址为0x842e9000,0xa737d000,0xa8611000。
- 针对strace抓取的syscall过滤三次地址内存分配的系统调用
可以发现tid 15671申请了19480576字节大小,地址为0xa8611000的匿名内存。通过writev确定泄露内存申请处于arcsoft_YUVNight_process_frame函数,检查该函数内的大内存申请,确定是为了超夜算法处理申请的内存未释放导致。