Men-debug Kerusakan Memori menggunakan Address Sanitizer

Dokumen ini menunjukkan cara mengaktifkan alat proses debug khusus saat menggunakan AGDE. Alat ini dapat membantu mengatasi kerusakan memori yang sulit didiagnosis dan menimpa error.

HWAddress Sanitizer dan Address Sanitizer

HWAddress Sanitizer (HWASan) dan Address Sanitizer (ASan) adalah alat proses debug kerusakan memori yang membantu proses debug kerusakan memori dan menimpa error, seperti berikut:

  • Overflow dan underflow buffer stack
  • Overflow dan underflow buffer heap
  • Penggunaan stack di luar cakupannya
  • Error double free dan wild free
  • Penggunaan stack setelah ditampilkan (khusus HWASan)

Sebaiknya aktifkan HWASan atau ASan hanya saat Anda men-debug masalah atau sebagai bagian dari pengujian otomatis. Meskipun alat ini berperforma tinggi, penggunaannya menimbulkan penalti.

Perilaku runtime

Jika diaktifkan, HWASan dan ASan akan otomatis memeriksa kerusakan memori di aplikasi Anda.

Jika error memori terdeteksi, aplikasi akan mengalami error dengan error SIGBART (pembatalan sinyal) dan mencetak pesan mendetail ke logcat. Salinan pesan ini juga ditulis ke file di bagian /data/tombstones.

Pesan error terlihat mirip dengan yang berikut ini:

ERROR: HWAddressSanitizer: tag-mismatch on address 0x0042a0826510 at pc 0x007b24d90a0c
WRITE of size 1 at 0x0042a0826510 tags: 32/3d (ptr/mem) in thread T0
    #0 0x7b24d90a08  (/data/app/com.example.hellohwasan-eRpO2UhYylZaW0P_E0z7vA==/lib/arm64/libnative-lib.so+0x2a08)
    #1 0x7b8f1e4ccc  (/apex/com.android.art/lib64/libart.so+0x198ccc)
    #2 0x7b8f1db364  (/apex/com.android.art/lib64/libart.so+0x18f364)
    #3 0x7b8f2ad8d4  (/apex/com.android.art/lib64/libart.so+0x2618d4)

0x0042a0826510 is located 0 bytes to the right of 16-byte region [0x0042a0826500,0x0042a0826510)
allocated here:
    #0 0x7b92a322bc  (/apex/com.android.runtime/lib64/bionic/libclang_rt.hwasan-aarch64-android.so+0x212bc)
    #1 0x7b24d909e0  (/data/app/com.example.hellohwasan-eRpO2UhYylZaW0P_E0z7vA==/lib/arm64/libnative-lib.so+0x29e0)
    #2 0x7b8f1e4ccc  (/apex/com.android.art/lib64/libart.so+0x198ccc)

Prasyarat

Persyaratan HWASan

Untuk menggunakan HWASan:

  • Anda harus menggunakan AGDE 24.1.99 atau yang lebih tinggi.
  • Aplikasi harus di-build menggunakan NDK 26 atau yang lebih tinggi.
  • Aplikasi harus di-build dengan target SDK 34 atau yang lebih tinggi.
  • Target harus berupa perangkat arm64-v8a yang menjalankan Android 14 (API level 34) atau yang lebih tinggi.

Menggunakan Library Standar C++ bersama dalam project Anda

Karena masalah umum, ASan tidak kompatibel dengan penanganan pengecualian C++ saat menggunakan libc++_static. Masalah ini tidak terlihat saat menggunakan libc++_shared.

HWASan memiliki implementasi operator new dan delete sendiri, yang tidak dapat digunakan jika library standar ditautkan secara statis ke project.

Untuk mengubah setelan ini, lihat bagian Menautkan Library Standar C++ dalam dokumen ini.

Mengaktifkan pembuatan Frame Pointer

HWASan dan ASan menggunakan unwinder berbasis frame pointer cepat dalam membuat informasi stack trace untuk peristiwa alokasi dan dealokasi memori. Ini berarti Anda harus mengaktifkan pembuatan pointer frame di setelan compiler C++ untuk menggunakan fitur ini. Artinya, Anda perlu menonaktifkan pengoptimalan penghilangan frame pointer.

Untuk mengubah setelan ini, lihat bagian Mengaktifkan pembuatan Frame Pointer dalam dokumen ini.

Mengonfigurasi project Visual Studio Anda untuk menggunakan HWASan atau ASan

Mengaktifkan HWASan atau ASan

Untuk mengaktifkan HWASan atau ASan, buka Configuration Properties > General di Property Pages untuk project Anda.

Menu properti Visual Studio Solution Explorer untuk project
saat ini.

Gambar 1: Opsi Property project di jendela Visual Studio Solution Explorer.

Dialog Halaman Properti project dengan properti Umum yang ditampilkan dan setelan
Address Sanitizer ditandai.

Gambar 2: Setelan Address Sanitizer (ASan) di properti project umum.

Untuk mengaktifkan HWASan untuk project Anda, ubah setelan Address Sanitizer (ASan) menjadi Hardware ASan Enabled (fsanitize=hwaddress).

Untuk mengaktifkan ASan untuk project Anda, ubah setelan Address Sanitizer (ASan) menjadi ASan Enabled (fsanitize=address).

Mengaktifkan pembuatan Frame Pointer

Pembuatan Frame Pointer dikontrol oleh setelan compiler C/C++ Omit Frame Pointer dan dapat ditemukan di Property Pages project di bagian Configuration Properties > C/C++ > Optimization.

Dialog Halaman Properti project dengan properti Pengoptimalan C/C++ ditampilkan,
dan setelan Hapus Frame Pointer
ditandai.

Gambar 3: Tempat untuk menemukan setelan Omit Frame Pointer.

Saat menggunakan HWASan atau ASan, tetapkan setelan Omit Frame Pointer ke No (-fno-omit-frame-pointer).

Menautkan Library Standar C++ dalam mode library bersama

Setelan mode penaut untuk Library Standar C++ dapat ditemukan di Property Pages project Anda di bagian Configuration Properties > General, di bagian Project Defaults.

Dialog Halaman Properti project dengan kategori Umum dipilih, dan
Penggunaan setelan STL ditandai.

Gambar 4: Tempat menemukan setelan mode penaut untuk Library Standar C++.

Saat menggunakan HWASan atau ASan, tetapkan Use of STL ke Use C++ Standard Libraries (.so). Nilai ini menautkan library standar C++ ke project Anda sebagai library bersama, yang diperlukan agar HWASan dan ASan dapat berfungsi dengan benar.

Membuat Konfigurasi Build untuk penggunaan Address Sanitizer

Jika Anda lebih suka menggunakan HWASan atau ASan untuk sementara, sebaiknya jangan membuat konfigurasi build baru hanya untuk penggunaannya. Hal ini mungkin terjadi jika project Anda kecil, Anda sedang menjelajahi fitur, atau sebagai respons atas masalah yang Anda temukan selama pengujian.

Namun, jika menurut Anda HWASan atau ASan berguna dan berencana menggunakannya secara rutin, sebaiknya buat konfigurasi build baru untuk HWASan atau ASan seperti yang ditunjukkan dalam contoh Teapot. Anda mungkin melakukannya jika, misalnya, secara rutin menjalankan Address Sanitizer sebagai bagian dari pengujian unit, atau selama pengujian asap dalam game semalam.

Membuat konfigurasi build terpisah mungkin sangat berguna jika Anda memiliki project besar yang menggunakan banyak library pihak ketiga yang berbeda tempat Anda biasanya menautkannya secara statis dengan library standar C++. Konfigurasi build khusus dapat membantu memastikan bahwa setelan project Anda selalu akurat setiap saat.

Untuk membuat konfigurasi build, dari Property Pages project Anda, klik tombol Configuration Manager…, lalu buka menu drop-down Active solution configuration. Kemudian, pilih , dan buat konfigurasi build baru dengan nama yang sesuai (misalnya, HWASan enabled).

Menggunakan HWASan dengan alokator memori kustom

HWASan secara otomatis mencegat memori yang dialokasikan melalui malloc (atau new) sehingga dapat memasukkan tag ke dalam pointer dan memeriksa ketidakcocokan tag.

Namun, saat menggunakan alokator memori kustom, HWASan tidak dapat otomatis mencegat metode alokasi memori kustom Anda. Oleh karena itu, jika Anda ingin menggunakan HWASan dengan alokator memori kustom, instrumentasikan alokator memori untuk memanggil HWASan secara eksplisit. Hal ini dapat dilakukan hanya dengan beberapa baris kode.

Prasyarat

Metode HWASan yang perlu Anda panggil ditentukan di header ini:

#include "sanitizer/hwasan_interface.h"

Menginstrumentasikan metode alokasi memori

  1. Alokasikan objek pada perincian dan perataan blok 16 byte. Misalnya, jika Anda memiliki alokator kumpulan yang menayangkan objek berukuran tetap berukuran 24 byte, bulatkan alokasi Anda hingga 32 byte, dan selaraskan ke 16 byte.

  2. Buat tag 8-bit. Tag Anda tidak boleh menggunakan nilai 0-16, karena nilai tersebut disediakan untuk penggunaan internal.

  3. Aktifkan HWASan untuk mulai melacak region memori dengan tag tersebut:

    __hwasan_tag_memory((void*) address, tag, size);
    
  4. Masukkan tag ke 8-bit atas pointer Anda:

    address = __hwasan_tag_pointer((void*) address, tag);
    

Membuat instrumen metode dealokasi memori

  1. Reset tag untuk region memori agar akses lebih lanjut melalui pointer bertag yang ada gagal:

    __hwasan_tag_memory(__hwasan_tag_pointer(ptr, 0), 0, size);
    

Bekerja dengan kumpulan objek yang dialokasikan sebelumnya

Jika alokator memori Anda mengalokasikan objek di kumpulan dan mengembalikan objek kembali ke kumpulan, bukan benar-benar membebaskannya, metode pengalokasian ulang Anda dapat langsung menimpa tag untuk memori dan pointer dengan nilai baru:

```
__hwasan_tag_memory(__hwasan_tag_pointer(ptr, 0), tag, size);
ptr = __hwasan_tag_pointer((void*)ptr, tag);
```

Jika Anda menggunakan teknik ini, metode alokasi tidak perlu memberi tag pada pointer atau blok memori, tetapi memberi tag pada pointer dan blok memori saat Anda mengalokasikan objek di kumpulan. Lihat contoh PoolAllocator untuk contoh yang menggunakan gaya ini.