Неинициализированная память в 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
tombstones и logcat
на наличие собственных сбоев. Подробнее об отладке нативного кода Android смотрите здесь .