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

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