ASan 是一种基于编译器的快速检测工具,用于检测原生代码中的内存错误。

ASan 可以检测以下问题:

堆栈和堆缓冲区上溢/下溢

释放之后的堆使用情况

超出范围的堆栈使用情况

重复释放/错误释放

build.gradle

参考android官网的说明,在模块的 build.gradle 中增加arguments:

android {

defaultConfig {

externalNativeBuild {

cmake {

# Can also use system or none as ANDROID_STL.

arguments "-DANDROID_ARM_MODE=arm", "-DANDROID_STL=c++_shared"

}

}

}

}

不过,我的工程里面加这个和不加好像没什么区别。因为我再defaultConfig里面已经指定了abi,这个应该不需要吧

defaultConfig {

applicationId "com.cam"

minSdkVersion 27

targetSdkVersion 27

versionCode 1

versionName "1.0.0"

ndk {

abiFilters "arm64-v8a"

}

}

CMakeLists.txt

在 CMakeLists.txt 中的设置compile option和link properties

target_compile_options(${TARGET} PUBLIC -fsanitize=address -fno-omit-frame-pointer)

set_target_properties(${TARGET} PROPERTIES LINK_FLAGS -fsanitize=address)

wrap.sh

从 Android O MR1(API 级别 27)开始,应用可以提供可封装或替换应用进程的封装 Shell 脚本。这样,应用就可对其应用启动过程进行自定义,比如修改ASAN_OPTIONS,以便在生产设备上使用 ASan。

将 android:debuggable 和 android:extractNativeLibs=true添加到应用Manifest.xml

将 ASan 运行时库添加到应用模块的 jniLibs 中。

将包含以下内容的 wrap.sh 文件添加到每个相同的目录中。

一定要建立目录resources/lib/arm64-v8a这样的目录,将wrap.sh放在这个目录下。

#!/system/bin/sh

HERE="$(cd "$(dirname "$0")" && pwd)"

export ASAN_OPTIONS=log_to_syslog=false,allow_user_segv_handler=1

ASAN_LIB=$(ls $HERE/libclang_rt.asan-*-android.so)

if [ -f "$HERE/libc++_shared.so" ]; then

# Workaround for https://github.com/android-ndk/ndk/issues/988.

export LD_PRELOAD="$ASAN_LIB $HERE/libc++_shared.so"

else

export LD_PRELOAD="$ASAN_LIB"

fi

"$@"

最终目录结构应该是下面这样:

└── app

└── src

└── main

├── jniLibs

│ ├── arm64-v8a

│ │ └── libclang_rt.asan-aarch64-android.so

│ ├── armeabi-v7a

│ │ └── libclang_rt.asan-arm-android.so

└── resources

└── lib

├── arm64-v8a

│ └── wrap.sh

├── armeabi-v7a

│ └── wrap.sh

然后就可以运行看看了,出现log中包含wrap.sh就对了。

wrap.sh : AddressSanitizer:DEADLYSIGNAL

wrap.sh : =================================================================

wrap.sh : ==26278==ERROR: AddressSanitizer: SEGV on unknown address 0x1680001e2fe602f3 (pc 0x007135a4ea48 bp 0x007fed72dac0 sp 0x007fed72d270 T0)

wrap.sh : ==26278==The signal is caused by a READ memory access.

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐