Android Native記憶體洩露檢測(針對Android7.0)
1. 需要合入一個
2. 執行指令
adb root
adb shell setprop libc.debug.malloc.program cameraserver
adb shell setprop libc.debug.malloc.options “backtrace_enable_on_signal leak_track”
adb shell ps | find /I “cameraserver”
adb shell kill -9 pid_of_cameraserver // restart cameraserver
adb shell ps | find /I “cameraserver”
adb shell kill -45 pid_of_cameraserver // begin capture
run use case
adb shell ps | find /I “cameraserver” // need be same as last one, otherwise cameraserver die
during test
adb shell kill -28 pid_of_cameraserver // sigwinch will dump the callstack has memory leak
3. kill -28的指令是可以重複執行的。
4. 先看一個測試DEMO
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<unistd.h> #include<termios.h> #include<string.h> char *mm = NULL; int main(void) { int cnt = 0; do { mm = (char *)malloc(4096); memset(mm,0x0,4096); usleep(1*1000*1000); printf("leak count = %d\n",cnt++); }while(1); return 0; }
上文中的malloc會最終呼叫到 bionic/libc/malloc_debug/malloc_debug.cpp中的debug_malloc函式。demo中每次洩漏4K的記憶體,我們隨後通過libc提供的feature定位到它。
4. 檢測步驟
a) setprop libc.debug.malloc.program leak
設定需要跟蹤的程序名稱
b) setprop libc.debug.malloc.options "backtrace_enable_on_signal leak_track"
設定跟蹤程序的記憶體洩漏項檢測
c) kill -9 殺掉該程序,同時重新啟動這個程序,以使得該程序之後的記憶體分配,帶有debug選項 d) kill -45 程序ID,傳送訊號到目標程序,啟動記憶體洩漏檢測 e) kill -28 程序ID,傳送訊號到目標程序,列印可疑的記憶體洩漏項
記憶體洩漏Log如下:
11-06 02:44:01.317 3565 3565 E malloc_debug: leak: Run: 'kill -45 3565' to enable backtracing.
11-06 02:44:01.318 3565 3565 E malloc_debug: leak: Run: 'kill -28 <pid of process>' to print memory leak information.
11-06 02:44:25.699 3565 3565 E malloc_debug: leak:3565 backtrace enabled.
11-06 02:44:33.851 3565 3582 E malloc_debug: PrintLeaks::leak:3565 backtrace printing. Thread = PrintLeaks Thread
11-06 02:44:33.852 3565 3582 E malloc_debug: +++ leak leaked memory dumping started +++
11-06 02:44:33.852 3565 3582 E malloc_debug: +++ total size: 40 K, total records: 1, top records: 1 +++
11-06 02:44:33.852 3565 3582 E malloc_debug: +++ Backtrace at time of allocation: total size 40960 (leak times: 10, avg size: 4096) +++
//這個時間點總共洩漏了40K,每次洩漏4K,持續了10次洩漏
11-06 02:44:33.852 3565 3582 E malloc_debug: #00 pc 0000000000000764 /system/bin/leak
11-06 02:44:33.852 3565 3582 E malloc_debug: #01 pc 000000000001a7d8 /system/lib64/libc.so (__libc_init+88)
11-06 02:44:33.852 3565 3582 E malloc_debug: #02 pc 0000000000000690 /system/bin/leak
11-06 02:44:33.853 3565 3582 E malloc_debug: +++ leak leaked memory dumping ended +++
11-06 02:44:42.341 3565 3587 E malloc_debug: PrintLeaks::leak:3565 backtrace printing. Thread = PrintLeaks Thread
11-06 02:44:42.342 3565 3587 E malloc_debug: +++ leak leaked memory dumping started +++
11-06 02:44:42.342 3565 3587 E malloc_debug: +++ total size: 76 K, total records: 1, top records: 1 +++
11-06 02:44:42.342 3565 3587 E malloc_debug: +++ Backtrace at time of allocation: total size 77824 (leak times: 19, avg size: 4096) +++
11-06 02:44:42.343 3565 3587 E malloc_debug: #00 pc 0000000000000764 /system/bin/leak
11-06 02:44:42.343 3565 3587 E malloc_debug: #01 pc 000000000001a7d8 /system/lib64/libc.so (__libc_init+88)
11-06 02:44:42.343 3565 3587 E malloc_debug: #02 pc 0000000000000690 /system/bin/leak
11-06 02:44:42.343 3565 3587 E malloc_debug: +++ leak leaked memory dumping ended +++
11-06 02:45:04.320 3565 3601 E malloc_debug: PrintLeaks::leak:3565 backtrace printing. Thread = PrintLeaks Thread
11-06 02:45:04.321 3565 3601 E malloc_debug: +++ leak leaked memory dumping started +++
11-06 02:45:04.321 3565 3601 E malloc_debug: +++ total size: 164 K, total records: 1, top records: 1 +++
11-06 02:45:04.321 3565 3601 E malloc_debug: +++ Backtrace at time of allocation: total size 167936 (leak times: 41, avg size: 4096) +++
5. 定位記憶體洩漏的位置
#gdb leak
(gdb) b *0x0000000000000764
Breakpoint 1 at 0x764: file hardware/rockchip/memleak/leak.cpp, line 27.
需要特別留意的是這裡的可執行檔案leak必須包含符號表(symbol目錄下),經過定位後,洩漏點在leak.cpp的第27行,結合之前的DEMO程式碼,確認正是此處洩漏。