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
和logcat
是否存在本機當機來監控錯誤的存在。有關調試 Android 本機代碼的更多信息,請參閱此處的資訊。