Неинициализированная память в C и C++ является распространенной причиной проблем с надежностью, ошибок безопасности памяти и утечек информации. Чтобы избежать этих проблем, Android инициализирует как можно больше памяти.
Нулевая инициализированная память пользовательского пространства
Начиная с Android 12, стековая память инициализируется нулем во всем собственном коде платформы (включая JNI), а память кучи инициализируется нулем во всех собственных процессах платформы (таких как netd
), но не в zygote
или в приложениях.
Приложениям первых и сторонних разработчиков, созданным с помощью NDK, настоятельно рекомендуется использовать флаг компилятора -ftrivial-auto-var-init=zero
для инициализации нулями локальных переменных стека. Компилятор оптимизирует все ненужные обнуления. Например, когда локальная переменная инициализируется явно (например, int x = 123;
переменная x
инициализируется только один раз). Если программа имеет большой буфер стека в горячей точке производительности, разработчик может отключить инициализацию, используя атрибут компилятора:
__attribute__((__uninitialized__)) char buf[BUFSIZ];
Приложения также могут выбрать нулевую инициализацию кучи, используя атрибут манифеста android:nativeHeapZeroInitialized
. Альтернативно, инициализацию нуля кучи можно контролировать во время выполнения с помощью:
int mallopt(M_BIONIC_ZERO_INIT, level)
Где уровень равен 0 или 1.
Нулевая инициализированная память ядра
Стек ядра и куча инициализируются нулями для ядер GKI, что настоятельно рекомендуется CDD .
Для инициализации стека GKI использует конфигурацию CONFIG_INIT_STACK_ALL_ZERO
, что приводит к сборке ядра с использованием флага компилятора -ftrivial-auto-var-init=zero
. Для инициализации кучи GKI использует CONFIG_INIT_ON_ALLOC_DEFAULT_ON
, который делает все выделения кучи страниц, SLAB и SLUB инициализированными нулями при их создании. Этот параметр по сути аналогичен передаче init_on_alloc=1
в качестве параметра времени загрузки ядра.
Отчеты об ошибках
Наши инструменты создают подробные отчеты об ошибках, которые содержат дополнительную информацию, помогающую при отладке. Дополнительная трассировка стека выделения и освобождения помогает лучше понять жизненный цикл данного выделения и гораздо быстрее приводит к возникновению корневых ошибок безопасности памяти.
Во время разработки поставщики должны отслеживать наличие ошибок, проверяя /data/tombstones
и logcat
на наличие встроенных сбоев. Дополнительную информацию об отладке нативного кода Android смотрите здесь .