零初始化內存

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/tombstoneslogcat來監控錯誤的存在,以發現本機崩潰。有關調試 Android 本機代碼的更多信息,請參閱此處的信息。