Android NDK поддерживает Address Sanitizer (также известный как ASan), начиная с уровня API 27 (Android O MR 1).
ASan — это быстрый инструмент на основе компилятора для обнаружения ошибок памяти в машинном коде. ASan обнаруживает:
- Переполнение или опустошение буфера стека и кучи
- Куча использования после бесплатного
- Использование стека за пределами области действия
- Двойное бесплатное/дикое бесплатное
Накладные расходы ЦП ASan составляют примерно 2x, накладные расходы на размер кода составляют от 50% до 2x, а накладные расходы на память велики (в зависимости от ваших шаблонов распределения, но порядка 2x).
Пример приложения
В примере приложения показано, как настроить вариант сборки для asan.
Строить
Чтобы создать собственный (JNI) код вашего приложения с помощью Address Sanitizer , выполните следующие действия:
ndk-сборка
В вашем Application.mk:
APP_STL := c++_shared # Or system, or none.
APP_CFLAGS := -fsanitize=address -fno-omit-frame-pointer
APP_LDFLAGS := -fsanitize=address
Для каждого модуля в вашем Android.mk:
LOCAL_ARM_MODE := arm
CMake
В build.gradle вашего модуля:
android {
    defaultConfig {
        externalNativeBuild {
            cmake {
                // Can also use system or none as ANDROID_STL.
                arguments "-DANDROID_ARM_MODE=arm", "-DANDROID_STL=c++_shared"
            }
        }
    }
}
Для каждой цели в вашем CMakeLists.txt:
target_compile_options(${TARGET} PUBLIC -fsanitize=address -fno-omit-frame-pointer)
set_target_properties(${TARGET} PROPERTIES LINK_FLAGS -fsanitize=address)
Бегать
Начиная с Android O MR1 (уровень API 27), приложение может предоставлять сценарий оболочки оболочки , который может обертывать или заменять процесс приложения. Это позволяет отлаживаемому приложению настраивать запуск своего приложения, что позволяет использовать ASan на производственных устройствах.
-  Добавьте android:debuggableв манифест приложения.
-  Установите useLegacyPackagingзначениеtrueв файлеbuild.gradleвашего приложения. Дополнительную информацию см. в руководстве по сценарию оболочки оболочки .
-  Добавьте библиотеку времени выполнения ASan в jniLibsвашего модуля приложения.
- Добавьте файлы - wrap.shсо следующим содержимым в каждый каталог вашего каталога- src/main/resources/lib.- #!/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 , ваша окончательная структура каталогов должна включать следующее:
<project root>
└── app
    └── src
        └── main
            ├── jniLibs
            │   ├── arm64-v8a
            │   │   └── libclang_rt.asan-aarch64-android.so
            │   ├── armeabi-v7a
            │   │   └── libclang_rt.asan-arm-android.so
            │   ├── x86
            │   │   └── libclang_rt.asan-i686-android.so
            │   └── x86_64
            │       └── libclang_rt.asan-x86_64-android.so
            └── resources
                └── lib
                    ├── arm64-v8a
                    │   └── wrap.sh
                    ├── armeabi-v7a
                    │   └── wrap.sh
                    ├── x86
                    │   └── wrap.sh
                    └── x86_64
                        └── wrap.sh
Трассировки стека
 Address Sanitizer должен разматывать стек при каждом вызове malloc / realloc / free . Здесь есть два варианта:
- «Быстрая» размотка на основе указателя кадра. Это то, что используется, следуя инструкциям в разделе строительства . 
- «Медленный» размотчик CFI. В этом режиме ASan использует - _Unwind_Backtrace. Для этого требуется только- -funwind-tables, который обычно включен по умолчанию.
 Быстрая размотка используется по умолчанию для malloc/realloc/free. Медленная размотка используется по умолчанию для фатальных трассировок стека. Медленную размотку можно включить для всех трассировок стека, добавив fast_unwind_on_malloc=0 в переменную ASAN_OPTIONS в вашем файле Wrap.sh.
