In my attempt to squash all bugs, I ran my Android app with clang's address sanitizer. Because the steps are not trivial, I thought I would documents the process here.
This recipe makes some assumptions, though:
- I'm on Linux.
- I use AndroidStudio with CMake.
- I run on the Android emulator. (A real device shouldn't be much different.)
First, we need to pass the -fsanitize=address flag to both the compiler and the linker. To compile your C/C++ code with this flag, use this in your CMakefile
target_compile_options(foo PRIVATE "$<$<CONFIG:DEBUG>:-fsanitize=address>" )
And to link, add "-fsanitize=address" to your target_link_libraries.
Ok, now your shared-object has been built with the address sanitizer. But if you try to run it, you will see: dlopen failed: library "libclang_rt.asan-i686-android.so" not found.
Luckily, the Android NDK comes with the correct libraries, you just need to package them with your build. First locate where this library is on your system, doing:
$ locate libclang_rt.asan-i686-android.so /home/bram/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/lib64/clang/8.0.7/lib/linux/libclang_rt.asan-i686-android.so
You simply need to copy this alongside your own shared object file, as generated by cmake. In my case, it goes in: ./app/build/intermediates/cmake/debug/obj/x86/libclang_rt.asan-i686-android.so
If you now build and run your app on the emulator, your addresses will get sanitized. In my first run, it found a free() of a pointer that was never malloc()-ed in the Google Play Games SDK.
Note that if you want to do this on a ARM device, you would need libclang_rt.asan-arm-android.so and on a 64-bit ARM device, look for libclang_rt.asan-aarch64-android.so instead.