分享

解决Android C 代码的内存泄漏一个重要的原则

 一书重 2018-01-01

C / C++程序员,毫无疑问,最头痛的问题是内存泄漏的问题。解决内存泄漏问题似乎很简单,这是一个原则,即必须立即释放所分配的内存。然而,在实际场景中,随着代码复杂度的增加,很难遵循这一原则。随着面向对象、模块化和多线程的引入,决定谁释放内存变得更加困难。为了解决这个问题,C++引入了智能指针和引用计数。但是,引用计数不能解决由两个对象互相引用引起的内存泄漏。在Android中,引入了强指针(SP)和弱指针(WP),试图解决两个对象相互参照的困境。然而,当球被抛给程序员时,程序员需要决定何时使用强指针以及何时定义弱指针。所以这个方案能不能解决内存泄漏问题非常喜欢java的GC。

由于内存泄漏似乎不可避免,我们需要做的是检查程序是否有内存泄漏并定位内存泄漏代码,然后解决它。这个过程不是那么简单,尤其是Android的C++代码。本文探讨的就是如何检查Android C++代码的内存泄漏,一个基于文档的官方Android原生内存:调试使用,但是这篇文章太简单,再加上Android系统和Android工具快速升级,一些方法在新的环境下是不合适的,咨询一些网络组合与实际数据和调试环境后,我们做了一个总结。

有时我们在网上找到一篇文章,但我们必须做这个或那个问题。究其原因是计算机技术发展得太快,各种软件版本频繁迭代,环境也不同。该方法可能需要做一些修改。本文所述方法需要两个先决条件:

  1. Android系统已经扎根,因为它需要将库推向系统;

  2. 与Android源代码相对应的Android系统版本,从Android源编译出我们需要的库。

我的工作环境是:

  • Ubuntu 16.04 LTS 64位操作系统

  • android 5.1源代码

  • Nexus 4手机(Android 5.1的AOSP系统)

如果是Android系统的另一个版本,它在理论上也适用。

Android系统使用一个精简版的libc,称为仿生,与代码位于Android源代码的仿生/ libc目录。调试,你需要编译libc_malloc_debug_leak.so和libc_malloc_debug_qemu.so,和这两个图书馆将在userdebug版本编译。我们可以只编译生成系统在userdebug状态或使用MM命令编译该模块只。

  1. 推libc_malloc_debug_leak.so和libc_malloc_debug_qemu.so的Android设备。

  2. malloc调试Android设备是通过以下命令打开:

adb root adb shell setprop libc.debug.malloc 1 adb shell stop adb shell start

注意:打开后的malloc调试,系统开始慢下来。请耐心等待,重新启动后恢复正常模式。

  1. 找到隐藏的文件夹为家。开发商$HOME目录下的Android,并添加一行本地=真正的ddms.cfg文件里面

  2. 下载旧版本的Android工具

最新的Android Studio Android设备提供监控,将DDMS的旧版本,但功能集成的版本是不完整的,所以请工具Android工具,老版本下载地址:http://dl.google.com/android/repository/tools_r25.2.5-linux.zip

  1. 解压tools_r25.2.5-linux.zip和工具目录下启动DDMS

  2. 你可以看到,DDMS界面有一个本机堆的标签页,切换到本地堆页面,选择在进程列表左侧的调试程序的过程,然后点击快照当前本机堆使用的按钮,抓住一个应用程序的本机内存泄漏,包含堆栈地址泄漏。

对示例应用程序的源代码,请参阅:https://github.com/mogoweb/android-testcode GitHub,一个简单的例子malloc_debug_leak。

在获取内存地址之后,我们还需要找到要执行的代码。需要注意的是,在加载和定位重要,动态链接库不能简单地通过addr2line工具找到的代码行。我们需要找到加载在内存中的基址。

  1. 使用ADB shell ps命令查找应用程序的PID

u0_a52 3509 2047 1530248 47880 ffffffff b6e790dc S com.china_liantong.memoryleaktest
  1. 使用ADB shell 3509命令来查找应用程序的内存映像

a3db7000-a3dcf000 r-xp 00000000 b3:17 276908 /data/app/com.china_liantong.memoryleaktest-2/lib/arm/libnative-lib.so
  1. 与r-xp标记线的代码在内存中的地址范围,和地址0xa3dbb2d2减去基地址0xa3db7000与libnative-lib.so内存泄漏点0xa3db7000得到的地址。

  2. 使用addr2line工具找到相应的代码行:

arm-linux-gnueabi-addr2line -C -f -e app/build/intermediates/cmake/debug/obj/armeabi-v7a/libnative-lib.so 0x042d2
  1. 您可以看到内存泄漏发生在第十四行中。

总结

这个malloc调试的原理是:当我们发现的libc.debug.malloc系统配置,系统将被重定向到分配/释放/新建/删除方法,在实施方法的相应lib_malloc_debug_leak.so,方法lib_malloc_debug_leak.so,一些记录信息,地址和其他信息将被记录,每次下堆栈。在需要的时候,通过工具DDMS转储,分析每个应用程序的内存,无论是正常释放,以及是否存在内存泄漏。

通过一个简单的例子说明了该方法的可行性。在实际项目中,可能是由于使用了内存缓存和内存池。可能的露点不是真正的内存泄漏,这需要程序员做出判断。也有可能,即使泄漏被发现,它将需要很多努力来解决它。无论如何,找出可疑的内存泄漏,是长征的第一步

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多