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