En este documento, se muestra cómo habilitar herramientas especiales de depuración cuando se usa AGDE. Estas herramientas pueden ayudar con la corrupción de la memoria difìcil de diagnosticar y reemplazar errores.
HWAddress Sanitizer y Address Sanitizer
HWAddress Sanitizer (HWASan) y Address Sanitizer (ASan) son herramientas para la corrupción de la memoria que ayudan a depurarla y reemplazar errores, por ejemplo:
- Desbordamiento y subdesbordamiento del búfer de pila
- Desbordamiento y desbordamiento del búfer del montón
- Uso de pila fuera de su alcance
- Errores de liberación doble y liberación salvaje
- Uso de pila después de la devolución (solo HWASan)
Te recomendamos que habilites HWASan o ASan solo cuando depures un problema o como parte de las pruebas automatizadas. Si bien estas herramientas tienen un buen rendimiento, su uso genera una sanción.
Comportamiento del tiempo de ejecución
Cuando se habilitan, HWASan y ASan verifican automáticamente la corrupción de la memoria en tu app.
Si se detecta un error de memoria, la app falla con un error SIGBART
(anulación de la señal) y, luego, imprime un mensaje detallado para logcat. También se escribe una copia del mensaje en un archivo dentro de /data/tombstones
.
El mensaje de error es similar al siguiente:
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)
Requisitos previos
Requisitos de HWASan
Para usar HWASan, haz lo siguiente:
- Debes usar AGDE 24.1.99 o una versión posterior.
- La app debe compilarse con el NDK 26 o una versión posterior.
- La app debe compilarse con el SDK de destino 34 o una versión posterior.
- El objetivo debe ser un dispositivo
arm64-v8a
que ejecute Android 14 (nivel de API 34) o una versión posterior.
Usa la biblioteca C++ estándar compartida en tu proyecto
Debido a un problema conocido, ASan no es compatible con el control de excepciones de C++ cuando se usa libc++_static
. Este problema no se observa cuando se utiliza libc++_shared
.
HWASan tiene su propia implementación de los operadores new
y delete
, que no se pueden usar si la biblioteca estándar está vinculada de forma estática al proyecto.
Para cambiar este parámetro, consulta la sección Vincula la biblioteca C++ estándar de este documento.
Cómo habilitar la generación de punteros de marco
HWASan y ASan usan un desenredador rápido basado en punteros de marco para generar información de seguimiento de pila para los eventos de asignación y desasignación de memoria. Esto significa que debes habilitar la generación de punteros de marco en la configuración de tu compilador de C++ para usar estas funciones. Es decir, debes inhabilitar la optimización de la omisión de punteros de marco.
Para cambiar este parámetro, consulta la sección Habilita la generación de punteros de marco de este documento.
Configura tu proyecto de Visual Studio para usar HWASan o ASan
Habilita HWASan o ASan
Para habilitar HWASan o ASan, ve a Configuration Properties > General en Property Pages de tu proyecto.
Figura 1: La opción Properties del proyecto en la ventana Solution Explorer de Visual Studio.
Figura 2: El parámetro Address Sanitizer (ASan) en las propiedades generales del proyecto.
Para habilitar HWASan para tu proyecto, cambia el parámetro Address Sanitizer (ASan) a Hardware ASan Enabled (fsanitize=hwaddress).
Para habilitar ASan para tu proyecto, cambia el parámetro Address Sanitizer (ASan) a ASan Enabled (fsanitize=address).
Habilita la generación de punteros de marco
La generación de punteros de marco está controlada por el parámetro del compilador de C/C++ Omit Frame Pointer de que se encuentra en Property Pages de tu proyecto dentro de Configuration Properties > C/C++ > Optimization.
Figura 3: Dónde encontrar el parámetro Omit Frame Pointer.
Cuando uses HWASan o ASan, establece el parámetro Omit Frame Pointer como No (-fno-omit-frame-pointer).
Vincula la biblioteca C++ estándar en el modo de biblioteca compartida
El parámetro de configuración del modo vinculador para la biblioteca C++ estándar se puede encontrar en Property Pages del proyecto dentro de Configuration Properties > General, en la sección Project Defaults.
Figura 4: Dónde encontrar el parámetro de configuración del modo vinculador para la biblioteca C++ estándar.
Cuando uses HWASan o ASan, configura Use of STL como Use C++ Standard Libraries (.so). Este valor vincula la biblioteca C++ estándar al proyecto como una biblioteca compartida, que es necesaria para que HWASan y ASan funcionen de forma correcta.
Crea una configuración de compilación para usar Address Sanitizer
Si prefieres usar HWASan o ASan de manera transitoria, te recomendamos que no crees una nueva configuración de compilación solo para su uso. Este podría ser el caso si tu proyecto es pequeño, exploras la función o buscas la respuesta a un problema que descubres durante la prueba.
Sin embargo, si te resulta útil y planeas usarlo con regularidad, te recomendamos que crees una configuración de compilación nueva para HWASan o ASan, como se observa en la muestra Teapot. Puedes hacerlo si, por ejemplo, ejecutas Address Sanitizer con regularidad como parte de tus pruebas de unidades o durante las pruebas nocturnas de humo del juego.
Crear una configuración de compilación independiente puede ser especialmente útil si tienes un proyecto grande que consume una gran cantidad de bibliotecas de terceros diferentes que sueles vincular, de forma estática, con la biblioteca C++ estándar. La configuración de compilación dedicadas puede ayudar a garantizar que la configuración de tu proyecto siga siendo precisa en todo momento.
Para crear una configuración de compilación, desde Property Pages del proyecto, haz clic en el botón Configuration Manager… y, luego, abre el menú desplegable Active solution configuration. Luego, selecciona
Cómo usar HWASan con asignadores de memoria personalizados
HWASan intercepta automáticamente la memoria asignada a través de malloc
(o new
) para poder insertar etiquetas en punteros y verificar si hay discrepancias.
Sin embargo, cuando se usa un asignador de memoria personalizado, HWASan no puede interceptar automáticamente tus métodos de asignación de memoria personalizados. Por lo tanto, si quieres usar HWASan con tu asignador de memoria personalizado, instrumenta tu asignador de memoria para llamar a HWASan de forma explícita. Esto se puede hacer con solo unas pocas líneas de código.
Requisitos previos
Los métodos de HWASan a los que debes llamar se definen en este encabezado:
#include "sanitizer/hwasan_interface.h"
Instrumenta tu método de asignación de memoria
Asignar objetos con alineación y nivel de detalle de bloque de 16 bytes Por ejemplo, si tienes un asignador de grupos que entrega objetos de tamaño fijo de 24 bytes, redondea tus asignaciones hasta 32 bytes y alinéalas a 16 bytes.
Genera una etiqueta de 8 bits. Tu etiqueta no debe usar valores del 0 al 16, ya que esos valores están reservados para uso interno.
Habilita HWASan para que comience a hacer un seguimiento de la región de memoria con esa etiqueta:
__hwasan_tag_memory((void*) address, tag, size);
Inyecta la etiqueta en los 8 bits superiores de tu puntero:
address = __hwasan_tag_pointer((void*) address, tag);
Instrumenta tu método de desasignación de memoria
Restablece la etiqueta de la región de memoria para que los accesos adicionales a través de los punteros etiquetados existentes fallen:
__hwasan_tag_memory(__hwasan_tag_pointer(ptr, 0), 0, size);
Cómo trabajar con un grupo de objetos preasignados
Si tu asignador de memoria asigna objetos de antemano en un grupo y los muestra nuevamente en el grupo en lugar de liberarlos, tu método de desasignación puede reemplazar directamente la etiqueta de la memoria y el puntero con un valor nuevo:
```
__hwasan_tag_memory(__hwasan_tag_pointer(ptr, 0), tag, size);
ptr = __hwasan_tag_pointer((void*)ptr, tag);
```
Si usas esta técnica, tus métodos de asignación no necesitan etiquetar punteros ni bloques de memoria, pero sí etiquetar los punteros y los bloques de memoria cuando asignas previamente los objetos en tu grupo. Consulta el ejemplo de PoolAllocator para ver un ejemplo que usa este estilo.