C 및 C++에서 초기화되지 않은 메모리는 안정성 문제, 메모리 안전 버그, 정보 유출의 일반적인 원인입니다. 이러한 문제를 방지하기 위해 Android에서는 최대한 많은 메모리를 초기화합니다.
0으로 초기화된 사용자 공간 메모리
Android 12부터 스택 메모리는 모든 플랫폼 네이티브 코드(JNI 포함)에서 0으로 초기화되고 힙 메모리는 모든 플랫폼 네이티브 프로세스(예: netd
)에서 0으로 초기화되지만 zygote
또는 앱에서는 0으로 초기화되지 않습니다.
NDK로 빌드된 퍼스트 파티 및 서드 파티 애플리케이션에서는 -ftrivial-auto-var-init=zero
컴파일러 플래그를 사용하여 스택 로컬 변수를 0으로 초기화하는 것이 좋습니다. 불필요한 0은 모두 컴파일러가 최적화합니다.
예를 들어 로컬 변수가 명시적으로 초기화되는 경우입니다(예: int x = 123;
변수 x
는 한 번만 초기화됨).
프로그램의 성능 핫스팟에 큰 스택 버퍼가 있는 경우 개발자는 컴파일러 속성을 사용하여 초기화를 사용 중지할 수 있습니다.
__attribute__((__uninitialized__)) char buf[BUFSIZ];
애플리케이션은 android:nativeHeapZeroInitialized
매니페스트 속성을 사용하여 힙 0 초기화를 선택할 수도 있습니다.
또는 런타임 시 다음을 사용하여 힙 0 초기화를 제어할 수 있습니다.
int mallopt(M_BIONIC_ZERO_INIT, level)
여기서 수준은 0 또는 1입니다.
0으로 초기화된 커널 메모리
커널 스택과 힙은 GKI 커널의 경우 0으로 초기화되며 이는 CDD에서 적극 권장합니다.
스택 초기화의 경우 GKI는 CONFIG_INIT_STACK_ALL_ZERO
구성을 사용하므로 -ftrivial-auto-var-init=zero
컴파일러 플래그를 사용하여 커널이 빌드됩니다.
힙 초기화의 경우 GKI는 CONFIG_INIT_ON_ALLOC_DEFAULT_ON
을 사용하므로 모든 페이지 힙, SLAB, SLUB 할당이 만들어질 때 0으로 초기화됩니다. 이 옵션은 init_on_alloc=1
을 커널 부팅 시간 옵션으로 전달하는 것과 사실상 유사합니다.
버그 신고
Google 도구는 디버깅에 도움이 되는 추가 정보가 포함된 유용한 버그 신고를 생성합니다. 추가 할당 및 할당 해제 스택 트레이스를 통해 지정된 할당의 수명 주기를 더욱 잘 파악할 수 있어 근본 원인이 되는 메모리 안전 버그를 훨씬 빠르게 찾아낼 수 있습니다.
개발 중에 공급업체는 /data/tombstones
및 logcat
에서 네이티브 충돌이 있는지 확인하여 버그의 존재를 모니터링해야 합니다. Android 네이티브 코드 디버깅에 관한 자세한 내용은 여기 정보를 참고하세요.