Нулевая инициализированная память

Неинициализированная память в 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 в качестве параметра времени загрузки ядра.

Отчеты об ошибках

Наши инструменты генерируют информативные отчеты об ошибках, которые содержат дополнительную информацию, помогающую в отладке. Дополнительная трассировка стека выделения и освобождения помогает лучше понять жизненный цикл данного распределения и значительно быстрее приводит к основным ошибкам безопасности памяти.

Пример отчета об ошибке, созданного инструментом безопасности памяти
Рис. 1. Отчеты об ошибках, созданные инструментами безопасности памяти.

Во время разработки поставщики должны отслеживать наличие ошибок, проверяя /data/tombstones tombstones и logcat на наличие собственных сбоев. Подробнее об отладке нативного кода Android смотрите здесь .