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

    xiaoxiao2021-04-18  79

    接前文, 之前讲了一堆 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/

    转载请注明原文地址: https://ju.6miu.com/read-675649.html

    最新回复(0)