零初始化內存

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 本機代碼的更多信息,請參閱此處的資訊。