Libc has a malloc debug framework for difference debugger. Each debugger takes as a libraries, and override the default malloc/free/calloc/realloc/, hooked before calling the real functions.
NOTE: This tip assume that you are working with an eng or userdebug build of the platform, not on a production device.
Bionic has a malloc debugger called leak debugger, which can record all the malloc/free in low level. And developers can use ddms on host to check each block of memory on heap by malloc. And ddms support convert caller function address to name conver. That makes easy for us to check which component, which function allocated for how many memories.
You can turn on memory tracking with debug level 1:
$ adb shell setprop libc.debug.malloc 1
$ adb shell stop
$ adb shell start
You need to restart the runtime so that zygote and all processes launched from it are restarted with the property set. Now all Dalvik processes have memory tracking turned on. You can look at these with DDMS, but first you need to turn on its native memory UI:
Upon relaunching DDMS and selecting a process, you can switch to the new native allocation tab and populate it with a list of allocations. This is especially useful for debugging memory leaks.
NOTE: to solve the module symbols, please export two env on HOST:
$ export PATH=$PATH:<android src>/prebuilt/linux-x86/toolchain/arm-linux-androideabi-4.4.x/bin
$ export ANDROID_PRODUCT_OUT=<android src>/out/target/product/<platform>
In this release he Electric Fence 2.2.0 has been ported to Android. it's also a memory debugger tool as above leak debugger.
It helps you detect two common programming bugs: software that overruns the boundaries of a malloc() memory allocation, and software that touches a memory allocation that has been released by free(). It will dump the call stack and mmap of the process, if the malloc/free is not called with correct parameters. It will also make a segment fault, when applications want to access the address which is freed.
The usage of efence is almost same as above, which we define it's debug level to 15:
$ adb shell setprop libc.debug.malloc 15
After setting this property, you can run your applications, and if there's any memory leakage, logcat will show information.
Example:
Access the memory, which has been freed already:
root@android:/data # setprop libc.debug.malloc 15
I/libc ( 4136): setprop using MALLOC_DEBUG = 1 (leak checker)
root@android:/data # ./memtest
I/libc ( 4138): ./memtest using MALLOC_DEBUG = 15 (efence)
F/libc ( 4138): Fatal signal 11 (SIGSEGV) at 0x4015bff4 (code=2)
I/DEBUG ( 3856): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
I/DEBUG ( 3856): Build fingerprint: 'freescale/sabresd_6dq/sabresd_6dq:4.0.4/R13.5-rc1/eng.b03824.20120711.11133
8:eng/test-keys'
I/DEBUG ( 3856): pid: 4138, tid: 4138 >>> ./memtest <<<
I/DEBUG ( 3856): signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 4015bff4
I/DEBUG ( 3856): r0 00000000 r1 00000002 r2 40151c6c r3 00000000
I/DEBUG ( 3856): r4 4015bff4 r5 bec75a54 r6 00000001 r7 bec75a5c
I/DEBUG ( 3856): r8 00000000 r9 00000000 10 00000000 fp 00000000
I/DEBUG ( 3856): ip 00000000 sp bec75a20 lr 40133f8f pc 0000a554 cpsr 60000010
I/DEBUG ( 3856): d0 203f810033915fe5 d1 0000000000000000
I/DEBUG ( 3856): d2 0000000000000000 d3 0000000000000000
I/DEBUG ( 3856): d4 0000000000000000 d5 0000000000000000
I/DEBUG ( 3856): d6 0000000000000000 d7 204cb48d00000000
I/DEBUG ( 3856): d8 0000000000000000 d9 0000000000000000
I/DEBUG ( 3856): d10 0000000000000000 d11 0000000000000000
I/DEBUG ( 3856): d12 0000000000000000 d13 0000000000000000
I/DEBUG ( 3856): d14 0000000000000000 d15 0000000000000000
I/DEBUG ( 3856): d16 41c0265a46a47ae1 d17 3f50624dd2f1a9fc
I/DEBUG ( 3856): d18 41c9c8aff2800000 d19 0000000000000000
I/DEBUG ( 3856): d20 0000000000000000 d21 0000000000000000
I/DEBUG ( 3856): d22 0000000000000000 d23 0000000000000000
I/DEBUG ( 3856): d24 0000000000000000 d25 0000000000000000
I/DEBUG ( 3856): d26 0000000000000000 d27 0000000000000000
I/DEBUG ( 3856): d28 0000000000000000 d29 0000000000000000
I/DEBUG ( 3856): d30 0000000000000000 d31 0000000000000000
I/DEBUG ( 3856): scr 00000010
I/DEBUG ( 3856):
I/DEBUG ( 3856): #00 pc 0000a554 /data/memtest
I/DEBUG ( 3856): #01 pc 00016834 /system/lib/libc.so (__libc_init)
I/DEBUG ( 3856):
I/DEBUG ( 3856): code around pc:
I/DEBUG ( 3856): 0000a534 e3a0000a ebfff8d1 e3a01001 e1a00004 ................
I/DEBUG ( 3856): 0000a544 e5c4100a ebfff8d9 e3560001 e3a03000 ..........V..0..
I/DEBUG ( 3856): 0000a554 e5c43000 0a000064 e59f21f0 e2857004 .0..d....!...p..
I/DEBUG ( 3856): 0000a564 e5954004 e08f1002 e1a00004 ebfff8c0 .@..............
I/DEBUG ( 3856): 0000a574 e3500000 0a00003f e59fc1d4 e1a00004 ..P.?...........
I/DEBUG ( 3856):
I/DEBUG ( 3856): code around lr:
I/DEBUG ( 3856): 40133f6c 68200701 0001f020 454e1046 2e00d018 .. h ...F.NE....
I/DEBUG ( 3856): 40133f7c 2102da01 1c81e000 43394338 f7eb4622 ...!....8C9C"F..
I/DEBUG ( 3856): 40133f8c 4605ed56 d1ec2800 da062e00 0101f008 V..F.(..........
I/DEBUG ( 3856): 40133f9c f06f4620 f7ea4200 4628e8d4 87f0e8bd Fo..B....(F....
I/DEBUG ( 3856): 40133fac eff0f7e9 6003234b 30fff04f bf00e7f6 ....K#.`O..0....
I/DEBUG ( 3856):
I/DEBUG ( 3856): memory map around addr 4015bff4:
I/DEBUG ( 3856): 40150000-4015a000
I/DEBUG ( 3856): 4015a000-4015d000
I/DEBUG ( 3856): 4015d000-4015e000
I/DEBUG ( 3856):
I/DEBUG ( 3856): stack:
I/DEBUG ( 3856): bec759e0 00000000
I/DEBUG ( 3856): bec759e4 00000000
I/DEBUG ( 3856): bec759e8 00000000
I/DEBUG ( 3856): bec759ec 4012090f /system/lib/libefence.so
I/DEBUG ( 3856): bec759f0 4015a014
I/DEBUG ( 3856): bec759f4 00002000
I/DEBUG ( 3856): bec759f8 00000004
I/DEBUG ( 3856): bec759fc 40120df1 /system/lib/libefence.so
I/DEBUG ( 3856): bec75a00 4015bff4
I/DEBUG ( 3856): bec75a04 bec75a54 [stack]
I/DEBUG ( 3856): bec75a08 00000001
I/DEBUG ( 3856): bec75a0c bec75a5c [stack]
I/DEBUG ( 3856): bec75a10 00000000
I/DEBUG ( 3856): bec75a14 400d9167 /system/lib/libc.so
I/DEBUG ( 3856): bec75a18 df0027ad
I/DEBUG ( 3856): bec75a1c 00000000
I/DEBUG ( 3856): #00 bec75a20 00008924 /data/memtest
I/DEBUG ( 3856): bec75a24 bec75a54 [stack]
I/DEBUG ( 3856): bec75a28 00000001
I/DEBUG ( 3856): bec75a2c bec75a5c [stack]
I/DEBUG ( 3856): bec75a30 00000000
I/DEBUG ( 3856): bec75a34 400d9837 /system/lib/libc.so
I/DEBUG ( 3856): #01 bec75a38 00000000
I/DEBUG ( 3856): bec75a3c 00000000
I/DEBUG ( 3856): bec75a40 00000000
I/DEBUG ( 3856): bec75a44 00000000
I/DEBUG ( 3856): bec75a48 00000000
I/DEBUG ( 3856): bec75a4c b00046ef /system/bin/linker
I/DEBUG ( 3856): bec75a50 00000001
I/DEBUG ( 3856): bec75a54 bec75b79 [stack]
I/DEBUG ( 3856): bec75a58 00000000
I/DEBUG ( 3856): bec75a5c bec75b83 [stack]
I/DEBUG ( 3856): bec75a60 bec75b8f [stack]
I/DEBUG ( 3856): bec75a64 bec75ba2 [stack]
I/DEBUG ( 3856): bec75a68 bec75bc5 [stack]
I/DEBUG ( 3856): bec75a6c bec75bde [stack]
I/DEBUG ( 3856): bec75a70 bec75c08 [stack]
I/DEBUG ( 3856): bec75a74 bec75c20 [stack]
I/DEBUG ( 3856): bec75a78 bec75c57 [stack]
I/DEBUG ( 3856): bec75a7c bec75c61 [stack]
I/BootReceiver( 3551): Copying /data/tombstones/tombstone_00 to DropBox (SYSTEM_TOMBSTONE)
D/dalvikvm( 3551): GC_CONCURRENT freed 398K, 10% free 8805K/9735K, paused 3ms+5ms
[2] + Segmentation fault ./memtest