在android上使用valgrind检测内存泄漏

    为 Android 开发了一个 native 程序,使用 C 语言。测试时观察内存占用,发现有内存泄漏。之前在 Linux 下使用过 valgrind ,于是想针对 Android 平台编译一个 Valgrind 版本,用来检测我的 native 程序。

    我的开发环境是 Windows 7,决定使用 Cygwin 来编译。

    Cygwin 的具体安装不多说了,注意的是,一些开发工具必须选择,比如 gcc 、 autoconf 、 automake 等等。

    Valgrind 最新的 release 版本是 3.9.0 ,官网下载。下载后解压,阅读源码根目录下的 README.android 文件,先有个初步了解。

    使用 Cygwin 来编译 Valgrind 和在 Linux 环境下编译还是有一些差别。我已经编译通过并正常使用。首先进入 Cygwin 的 shell ,然后,下面是详细的步骤。


    (一)设置 NDK 路径

    命令很简单,export NDKROOT=E:/android-ndk-r8d (替换为你开发主机上的实际路径)。

    需要注意的是,这里的 NDKROOT 不能用 Cygwin 挂载的路径 /cygdrive/e/xxx 这种形式,否则 configure 时检测工具链是否可以生成可执行文件时会找不到 ctrbegin_dynamic.o 及 C 库,导致 configure 失败。这个花费了我将近一个小时的时间!

    (二)设置硬件型号

    export HWKIND=generic

    我设置了上面的类型,实际应用中可以和具体的目标设备关联起来。

    (三)设置工具链

    这里和 README.android 稍有不同。具体如下:

export AR=$NDKROOT/toolchains/arm-linux-androideabi-4.4.3/prebuilt/windows/bin/arm-linux-androideabi-ar.exe
export LD=$NDKROOT/toolchains/arm-linux-androideabi-4.4.3/prebuilt/windows/bin/arm-linux-androideabi-ld.exe
export CC=$NDKROOT/toolchains/arm-linux-androideabi-4.4.3/prebuilt/windows/bin/arm-linux-androideabi-gcc.exe

    (四)配置( configure )

     先进入到 valgrind 源码根目录。

    找到 configure 文件,做一些修改,否则 configure 会失败。因为 configure 会检测编译主机内核版本,Cygwin 的 uname -r 返回的版本不是 Linux 内核版本号,我的环境返回是 1.7.28(0.271/5/3) 。找到 5508 行,修改成下面的样子(在2.6.*前加入了1.7.*):

        case "${kernel}" in
             1.7.*|2.6.*|3.*)
    这样内核版本检测才会通过。

    配置选项还要做一些修改,这里和 README.android 稍有不同,我添加 LIBS 选项,修改了 --target 。具体如下:

CPPFLAGS="--sysroot=$NDKROOT/platforms/android-14/arch-arm -DANDROID_HARDWARE_$HWKIND" \
  CFLAGS="--sysroot=$NDKROOT/platforms/android-14/arch-arm"  \
  LIBS="-L$NDKROOT/platforms/android-14/arch-arm/usr/lib" \
  ./configure --prefix=/data/local/Inst --host=armv7-unknown-linux \
  --target=arm-linux-androideabi  --with-tmpdir=/sdcard
    (五) 编译

    执行 make ,就这么简单了,我这里通过了。

    (六)安装

    make install ,这里会失败。我的错误信息如下:

make[2]: Entering directory '/cygdrive/e/sources/valgrind-3.9.0/VEX'
priv/.deps/libvex_arm_linux_a-host_s390_defs.Po:1: *** 多个目标匹配。 停止。
make[2]: Leaving directory '/cygdrive/e/sources/valgrind-3.9.0/VEX'
Makefile:665: recipe for target 'install-recursive' failed
make[1]: *** [install-recursive] Error 1
make[1]: Leaving directory '/cygdrive/e/sources/valgrind-3.9.0'
Makefile:990: recipe for target 'install' failed
make: *** [install] Error 2
    我没有搭理它,因为我发现 valgrind 和 memcheck 已经编译出来,决定放到目标设备上跑跑看,一跑,成功了!
    实际上为了做内存检测,需要 valgrind 、memcheck 、default.supp 、 vgpreload_core-arm-linux.so 、vgpreload_memcheck-arm-linux.so 这五个文件, push 到设备上即可。

    (六)运行

    像上面那样 push 程序到设备上,要想运行,必须设置一个环境变量 VALGRIND_LIB ,valgrind 会根据这个环境变量来查找要加载的工具,如 memcheck 等,否则会报错,找不到文件。

    现在可以这么启动目标程序了:

/data/data/valgrind/valgrind --leak-check=full --track-origins=yes --log-file=check.log  your-target-executable
    我们把日志输出到 check.log 文件中,方便查看。


    ------------
    好啦,到现在为止, valgrind for android 已经可以使用了。

    整个过程花了我 2 个多小时,对着 Cygwin 下面的报错,查看 config.log ,修改命令,修改 configure ,push 到设备上运行,根据出错信息找缺失的文件……不过还是相当值得,利器在手啦。

你可能感兴趣的:(android,cygwin,内存泄漏,native,memcheck)