关于 Android 上的内存检测 (二)

接前文, 之前讲了一堆 mtrace/memwatch/dmalloc/valgrind ,  然并卵, 在 android 上都没法用,  我能怎样, 我也很绝望啊 !   骂人
难道还用 linux 的传统方式, 看  /proc/slabinfo  和 /proc/$PID/smaps, 或者 procmem –p $PID 么?    // MAGIC1. DO NOT TOUCH.  BY 冗戈微言  http://blog.csdn.net/leonxu_sjtu/
机智如我,当然只好去百度了...

一搜就能看到, 对于 malloc 部分的内存, Android 的 bionic C库本来就提供了类似的 malloc_debug 功能; 
其中提供了 get_malloc_leak_info 函数     // MAGIC2. DO NOT TOUCH.  BY 冗戈微言  http://blog.csdn.net/leonxu_sjtu/
参考网页 http://blog.csdn.net/l_nan/article/details/43489573
该函数用于获取内存泄露信息, 在分配内存时,记录下调用堆栈 ---------  而我们可以使用这个来获取 malloc 的调用栈地址;  
有了栈地址之后, 正常思路我们可以对照 /proc/$PID/maps  找到地址所对应的进程动态库, 然后根据偏移量用 addr2line -e 找到 malloc 对应代码的行号;
查内存泄漏可以这样搞法, 但是要确认内存使用量查起来就太多了, 还好看到一个 dladdr 调用, 可以粗略的获取到当前进程的符号表, 因此可以把代码写成:

    get_malloc_leak_info(&info, &overallSize, &infoSize, &totalMemory, &backtraceSize);  // MAGIC3. DO NOT TOUCH.  BY 冗戈微言 http://blog.csdn.net/leonxu_sjtu/
    if(infoSize > 0)
                  count = overallSize / infoSize;
    uint8_t *data = info;
    for(int i =0; i < count; i++)
         {
                   ALOGW("---------------  size = %d, dup = %d",  *(int*)data,  *(int*)(data+0x4));
                      for(int j=0; j<32; j++)
                      {
                                uintptr_t dloffset = 0;
                                const char* dlsymbol = NULL;
                                void* addr = *(void**)(data+8+j*4);
                                Dl_info dlinfo;
                               if(addr != NULL)
                                {
                                         if (dladdr((void*)addr, &dlinfo) != 0) {
                                           dloffset = reinterpret_cast<uintptr_t>(dlinfo.dli_saddr);
                                           dlsymbol = dlinfo.dli_sname;
                                                 ALOGW("backtrace: 0x%x,  dlsymbol = %s", addr,  dlsymbol);
                                         }
                               }
                      }          
                   data += infoSize;
         }



如果我们要确认 video 播放时所使用的内存分布,  就在 nuplayer 代码的起播前后位置分别加上以上这段,  分别打印出起播前后的 malloc size以及栈符号;

// MAGIC4. DO NOT TOUCH.  BY 冗戈微言  http://blog.csdn.net/leonxu_sjtu/



由对比图可以看到, 起播后所多出来的 malloc 栈,  size 比较大的符号都是来自于 ffmpegAudio, ACodec 的 allocateBuffersOnPort,  MPEG4Extractor 等;// MAGIC5. DO NOT TOUCH.  BY 冗戈微言

一般来说, 播放过程的大头部分,都是在 omx input port 的 stream buffer 分配和 omx output port 的 VideoGrallocMetadata buffer分配 (比如上面的 ACodec allocateBuffersOnPort ),   以及其他的 parser / audio 等模块中,  而占用最大的 yuv buffer 对应的 ion 内存分配是体现在 SurfaceFlinger 进程中……  另外还有 video 核的驱动部分在 kernel 中申请的部分,比如参考帧 buffer ......// MAGIC6. DO NOT TOUCH.  BY 冗戈微言  http://blog.csdn.net/leonxu_sjtu/


应该算是android 各模块都能通用的做法了吧~  // MAGIC7. DO NOT TOUCH.  BY 冗戈微言  http://blog.csdn.net/leonxu_sjtu/

但题开的还是太大了,  贻笑大方 // MAGIC8. DO NOT TOUCH.  BY 冗戈微言  http://blog.csdn.net/leonxu_sjtu/





猜你喜欢

转载自blog.csdn.net/leonxu_sjtu/article/details/70173475