本农目前在搞安卓平台C++进程开发,最近线上报故障,我们的进程启动时崩溃,错误以前从未见过,
Fatal signal 11 (SIGSEGV), code 1, fault addr 0x6 in tid 223(HandlingMessageXXXX),
这个HandlingMessageXXXX是我们一个线程,问题是这个线程语句看不出什么问题。我们想复现这个故障,但是测了整整一天都没有复现,我想可能崩溃点并不在这个线程里,但是在哪呢?我们这个进程有效代码7-8w行,挨个找无异于大海捞针,所以我想借助内存检测工具来找内存泄漏/溢出点。最终找到了valgrind这个工具,我在ubuntu下很轻松就编译成功,但最终目标是要在安卓设备上使用,所以,就需要交叉编译。
32/64位valgrind程序,已编译完成,嫌配置过程麻烦的,可以直接下载使用
32/64位valgrind程序下载https://download.csdn.net/download/oqqsoap1234567/14032595
下面开始配置过程。
(一)设置 NDK 路径
直接在命令行敲,(替换为你开发主机上的实际路径)。敲完注意再echo下,检查是否设置正确。
export NDKROOT=/home/myname/AOSP_Code/prebuilts
echo $NDKROOT
我使用的是AOSP环境,ndk直接就包含在prebuilts里面了。
注意啊,所有的命令都要在解压后的valgrind根目录下敲,否则,环境变量设置无效,没法编译
可以看到,我使用的版本是3.16.1
(二)设置硬件型号
继续敲,我就不上图了, 我设置了下面的类型,实际应用中可以和具体的目标设备关联起来。
export HWKIND=generic
(三)设置工具链路径
注意:valgrind源码可以编译成32/64位,分别用于检测32/64位程序,需要AR,LD,CC3个工具,32/64位工具所对应的工具名称路径各不相同,注意不要搞错了,比如下面这种报错,结合实际情况和网上说法,总结了3种可能性
1.系统找不到memcheck路径,这是由于–prefix指定路径和安卓设备路径不同,见步骤”(四)配置( configure )“
2.缺少./autogen.sh(我没遇到这种情况)
3.待检测程序是64位的,而编译的valgrind是32位的,因此导致 valgrind运行失败
valgrind: failed to start tool 'memcheck' for platform \
'arm64-linux': No such file or directory
如果你不确定待检测程序是32还是64位,可以用file命令检测,例如:下面test程序就是64位,所以我们要选择64位工具链
file ~/test/Mutex/test
/home/myname/test/Mutex/test: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=e8789251befb8892fec8a05639ef31ef11e37863, not stripped
若不知道具体路径,所以根据名称使用find命令去查找。
以下为32位工具名称
arm-linux-androideabi-ar
arm-linux-androideabi-ld
arm-linux-androideabi-gcc
以下为64位工具名称
aarch64-linux-android-ar
aarch64-linux-android-ld.bfd
aarch64-linux-android-gcc
以下为找到的32位工具路径
./gcc/linux-x86/arm/arm-linux-androideabi-4.8/bin/arm-linux-androideabi-ar
./gcc/linux-x86/arm/arm-linux-androideabi-4.8/bin/arm-linux-androideabi-ld
./gcc/linux-x86/arm/arm-linux-androideabi-4.8/bin/arm-linux-androideabi-gcc
找到编译链接工具路径后,进行设置,以下为32位工具链设置。
export AR=$NDKROOT/gcc/linux-x86/arm/arm-linux-androideabi-4.8/bin/arm-linux-androideabi-ar
export LD=$NDKROOT/gcc/linux-x86/arm/arm-linux-androideabi-4.8/bin/arm-linux-androideabi-ld
export CC=$NDKROOT/gcc/linux-x86/arm/arm-linux-androideabi-4.8/bin/arm-linux-androideabi-gcc
以下为64位工具链设置
export AR=$NDKROOT/gcc/linux-x86/aarch64/aarch64-linux-android-4.8/bin/aarch64-linux-android-ar
export LD=$NDKROOT/gcc/linux-x86/aarch64/aarch64-linux-android-4.8/bin/aarch64-linux-android-ld.bfd
export CC=$NDKROOT/gcc/linux-x86/aarch64/aarch64-linux-android-4.8/bin/aarch64-linux-android-gcc
(四)配置( configure )
需要配置以下3个环境变量
CPPFLAGS
CFLAGS
LIBS
这里要注意下ndk路径,大家可以看下ndk目录结构。
继续敲,以下为32位配置路径
export CPPFLAGS="--sysroot=$NDKROOT/ndk/9/platforms/android-14/arch-arm -DANDROID_HARDWARE_$HWKIND"
export CFLAGS="--sysroot=$NDKROOT/ndk/9/platforms/android-14/arch-arm"
export LIBS="-L$NDKROOT/ndk/9/platforms/android-14/arch-arm/usr/lib"
export CPPFLAGS="--sysroot=$NDKROOT/ndk/9/platforms/android-21/arch-arm64 -DANDROID_HARDWARE_$HWKIND"
export CFLAGS="--sysroot=$NDKROOT/ndk/9/platforms/android-21/arch-arm64"
export LIBS="-L$NDKROOT/ndk/9/platforms/android-21/arch-arm64/usr/lib"
进行32位程序configure
运行valgrind目录下的configure命令
./configure --prefix=/data/local/Inst --host=armv7-unknown-linux \
--target=arm-linux-androideabi --with-tmpdir=/sdcard
注意,以下为程序安装的路径(make install),要使程序正常运行,有以下2种方法:
--prefix=/data/local/Inst
1.copy到安卓设备上要与此路径完全相同
2.配置lib环境变量,导出VALGRIND_LIB路径,用法如下(假设valgrind已经被安装到/home/test/valgrind目录),这样允许copy到安卓设备路径和–prefix指定路径不同,但是每次重启设备都需要配置一次,比较麻烦:
export VALGRIND_LIB=/home/test/valgrind/lib/valgrind
否则执行会报错,错误信息见步骤”(三)设置工具链路径“
进行64位程序configure
./configure --prefix=/data/local/Inst --host=aarch64-linux \
--enable-only64bit --with-tmpdir=/sdcard
报错如下:
configure: error: C compiler cannot create executables
See `config.log' for more details.
进入config.log查看
vi config.log
aarch64-linux-android-gcc: error: unrecognized command line option '-V'
aarch64-linux-android-gcc: fatal error: no input files
compilation terminated.
基本可以确定工具链配错导致,就是CPPFLAGS,CFLAGS,LIBS这3个环境变量配置路径不对,用echo重新检查一遍
出现如下提示,则说明交叉编译环境配置成功
Maximum build arch: arm
Primary build arch: arm
Secondary build arch:
Build OS: linux
Link Time Optimisation: no
Primary build target: ARM_LINUX
Secondary build target:
Platform variant: android
Primary -DVGPV string: -DVGPV_arm_linux_android=1
Default supp files: xfree-3.supp xfree-4.supp bionic.supp
64位是这样的
Maximum build arch: arm64
Primary build arch: arm64
Secondary build arch:
Build OS: linux
Link Time Optimisation: no
Primary build target: ARM64_LINUX
Secondary build target:
Platform variant: android
Primary -DVGPV string: -DVGPV_arm64_linux_android=1
Default supp files: xfree-3.supp xfree-4.supp bionic.supp
注意,Platform variant一定要是android,如果是vanilla,说明环境没配好,仍然是ubuntu的编译工具,需要重新检查路径。
Platform variant: vanilla
(五)编译安装( make )
敲2个命令
make
make install
最终生成的程序会copy到/data/local/Inst目录中,注意是否有权限,无权限会导致copy失败。
至此,交叉编译完成。
(六)安卓设备测试( test )
将valgrind程序及依赖库拷贝至安卓设备上,分别在/data/local/Inst下的bin和lib/valgrind目录里,共计5个文件
default.supp
memcheck-arm-linux
valgrind
vgpreload_core-arm-linux.so
vgpreload_memcheck-arm-linux.so
进入安卓设备的shell环境,设置环境变量VALGRIND_LIB为上面文件的拷贝目录,以便valgrind能够找到相关的库和可执行文件(实际上这一步骤我没做,因为我的–prefix路径和copy到安卓设备路径相同)。
export VALGRIND_LIB="/data/lib"
The end, Run
/data/lib/valgrind --leak-check=full --track-origins=yes --log-file=leak.log
/data/MyNativeProgram
我参考了以下几位Up的博客,在他们的基础上结合自己实际环境修改了一些内容
感谢!
参考文献:
32bit工具链配置https://blog.csdn.net/loushuai/article/details/51745473
64bit工具链配置https://blog.csdn.net/m0_37874806/article/details/105590314
缺少./autogen.sh导致failed to start tool 'memcheck’https://blog.csdn.net/gllg1314/article/details/78772123
32/64位版本不匹配导致failed to start tool 'memcheck’https://blog.csdn.net/yasi_xi/article/details/7594517
valgrind运行参数配置https://blog.csdn.net/foruok/article/details/20701991