Depurador

Depura tu proyecto con Visual Studio Debugger (LLDB) cuando uses Android Game Development Extension.

Ejecuta el depurador

Para poder ejecutar el depurador, debes poder compilar, implementar y ejecutar tu juego en Android. Si deseas obtener más información, consulta la sección Ejecuta la muestra.

Una vez que te asegures de que puedes ejecutar tu juego sin el depurador, podrás usar este último presionando F5 o seleccionando el elemento Start Debugging del menú Debug. Deberías ver un diálogo mientras el depurador se adjunta al juego.

Iniciar el depurador toma entre 10 segundos y 1 minuto o más, según el tamaño de tu aplicación y la cantidad de símbolos que se deban cargar durante el inicio. Tomará más tiempo cuando lo adjuntes a un dispositivo nuevo por primera vez, ya que el depurador deberá descargar algunas bibliotecas de Android del dispositivo a la máquina anfitrión. Si tarda más de 1 minuto en los primeros intentos con un dispositivo nuevo, considera cancelar la sesión de depuración y luego reiniciarla.

Cuando ejecutes el depurador de esta manera, el juego se iniciará en modo Waiting for Debugger ("Esperando el depurador") y no ejecutará el código de tu juego hasta que se conecte el depurador. Esto también te permite depurar la sección de inicialización de tu juego.

Si deseas obtener más información sobre las funciones específicas del depurador de Visual Studio, consulta la documentación de Visual Studio.

Adjunta el depurador a un proceso

Si quieres depurar un juego que ya se está ejecutando en un dispositivo físico o virtual, puedes adjuntar el depurador al proceso desde Visual Studio.

En Visual Studio, asegúrate de que una solución de Android esté abierta y realiza lo siguiente:

  1. Ve al menú Debug y selecciona Attach to Process….
  2. En el menú desplegable Transport, selecciona Android Game Development Extension.
  3. En el menú desplegable Qualifier, selecciona tu dispositivo Android.
  4. Elige el proceso del juego en la lista de procesos disponibles y haz clic en Attach.

Adjunta a un proceso

Ejecuta comandos de LLDB.Shell

Con una sesión de depuración activa, usa la ventana de comandos de Visual Studio para ejecutar los comandos de LLDB.Shell.

Formato del comando:

LLDB.Shell [command]

Ejemplo:

>LLDB.Shell expr myIntVariable = 9
Status:  Success
Output Message:
(int) $2 = 9

Visualización de datos

Especificadores de formato

Puedes cambiar el formato en el que se muestra un valor en los campos Autos, Locals, Watch y las distintas ventanas de DataTip con los especificadores de formato.

Los especificadores de formato se encuentran al final de las expresiones. Comienzan con una coma seguida de una string corta. Por ejemplo, el especificador ,x en la expresión _myInt,x dará formato a myInt como hexadecimal en minúsculas.

Los especificadores de formato se pueden usar directamente en la ventana Watch o bien en las ventanas Autos, Locals y DataTip agregándolos a las expresiones Natvis. Consulta Natvis para obtener más información.

Lista de especificadores compatibles

Nombre del formato Especificadores Descripción
boolean B muestra esto como un booleano verdadero/falso, usando la regla habitual en la que 0 corresponde a falso y todo lo demás a verdadero
binario b muestra esto como una secuencia de bits
binario, sin el prefijo 0b bb muestra esto como una secuencia de bits sin el prefijo 0b
bytes y muestra los bytes, pero también intenta hacerlo como caracteres ASCII
p. ej., (int *) c.sp.x = 50 f8 bf 5f ff 7f 00 00 P.._.…
bytes con ASCII Y muestra los bytes, pero también intenta hacerlo como caracteres ASCII
p. ej., (int *) c.sp.x = 50 f8 bf 5f ff 7f 00 00 P.._.…
carácter c muestra los bytes como caracteres ASCII
p. ej., (int *) c.sp.x = P\xf8\xbf_\xff\x7f\0\0
carácter imprimible C muestra los bytes como caracteres ASCII imprimibles
p. ej., (int *) c.sp.x = P.._.…
número de punto flotante complejo F interpreta este valor como la parte real y la imaginaria de un número complejo de punto flotante
p. ej., (int *) c.sp.x = 2.76658e+19 + 4.59163e-41i
decimal d, i muestra esto como un número entero con signo (no realiza una conversión, solo muestra los bytes como un número entero con signo)
enumeración E, en muestra esto como una enumeración e imprime el nombre del valor si está disponible o el valor de número entero si no lo está
p. ej., (enum enumType) val_type = eValue2
hexadecimal: minúsculas x, h muestra esto en notación hexadecimal en minúsculas (no realiza una conversión, solo muestra los bytes como hexadecimal)
hexadecimal: mayúsculas X, H muestra esto en notación hexadecimal en mayúsculas (no realiza una conversión, solo muestra los bytes como hexadecimal)
hexadecimal: minúsculas, sin el prefijo 0x xb, hb muestra esto en notación hexadecimal en minúsculas sin el prefijo 0x (no realiza una conversión, solo muestra los bytes como hexadecimal)
hexadecimal: mayúsculas, sin el prefijo 0x Xb, Hb muestra esto en notación hexadecimal en mayúsculas sin el prefijo 0x (no realiza una conversión, solo muestra los bytes como hexadecimal)
flotante f muestra esto como un número de punto flotante (no realiza una conversión, solo interpreta los bytes como un valor de punto flotante IEEE754)
octal o muestra esto en notación octal
Tipo de SO O muestra esto como un MacOS OSType
p. ej., (float) x = '\n\x1f\xd7\n'
string: string C s muestra esto como una string C terminada en 0
p. ej., "hello world"
string: string C, sin comillas sb muestra esto como una string C terminada en 0 sin comillas,
p. ej., hello world
string: UTF-8 s8 muestra esto como una string UTF-8 terminada en 0
p. ej., u8"hello world ☕"
string: UTF-8, sin comillas s8b muestra esto como una string UTF-8 terminada en 0 sin comillas
p. ej., hello world ☕
string: UTF-16 su muestra esto como una string UTF-16 terminada en 0
p. ej., u"hello world ☕"
string: UTF-16, sin comillas sub muestra esto como una string UTF-16 terminada en 0 sin comillas
p. ej., hello world ☕
string: UTF-32 s32 muestra esto como una string UTF-32 terminada en 0
p. ej., U"hello world" ☕"
string: UTF-32, sin comillas s32b muestra esto como una string UTF-32 terminada en 0 sin comillas
p. ej., hello world ☕
unicode16 U muestra esto como caracteres UTF-16
p. ej. (float) x = 0xd70a 0x411f
unicode32 U32 muestra esto como caracteres UTF-32
p. ej., (float) x = 0x411fd70a
decimal sin signo u muestra esto como un número entero sin signo (no realiza una conversión, solo muestra los bytes como un número entero sin signo)
puntero p muestra esto como un puntero nativo (a menos que esto sea un puntero real, la dirección resultante probablemente no sea válida)
número entero complejo I interpreta este valor como la parte real y la imaginaria de un número entero complejo
p. ej., (int *) = 1048960 + 1i
array de caracteres a muestra esto como un array de caracteres
p. ej., (char) *c.sp.z = {X}
Sin procesar ! formato sin procesar, que ignora cualquier personalización de vistas de tipo de datos

Natvis

El framework de Natvis te permite personalizar la forma en que Visual Studio muestra los tipos nativos en las ventanas de variables del depurador. Por ejemplo, usa Natvis a fin de personalizar las pantallas de las ventanas Watch, Locals y Data Tips.

La función de Natvis está habilitada de forma predeterminada, pero se puede inhabilitar desde Visual Studio estableciendo la marca Tools > Options > Android Game Development Extension > Natvis como Disabled.

Carga archivos de Natvis

Visual Studio carga los archivos de Natvis de las tres ubicaciones que se indican a continuación y los vuelve a cargar cada vez que inicias una sesión de depuración. Los archivos deben cumplir con el esquema de Natvis de Visual Studio 2017.

  • Los archivos .natvis que forman parte de un proyecto cargado o un elemento de solución de nivel superior
  • El directorio específico del usuario (%USERPROFILE%\Documents\Visual Studio 2017\Visualizers)
  • El directorio de todo el sistema (%VSINSTALLDIR%\Common7\Packages\Debugger\Visualizers)
Vuelve a cargar los archivos de Natvis

Vuelve a cargar los archivos de Natvis durante una sesión de depuración evaluando .natvisreload en la ventana de comandos o en la de inspección.

Archivo de Natvis de ejemplo

Este archivo de Natvis de ejemplo incluye todas las etiquetas y los atributos que se admiten actualmente.

<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">

  <Type Name="demo::Vector&lt;*&gt;">
    <AlternativeType Name="MySimilarVectorType&lt;*&gt;"/>

    <!-- Included to show the <SmartPointer> feature is supported. -->
    <SmartPointer Optional="true" Usage="Minimal">ptr</SmartPointer>

    <!-- Included to show the <DisplayString> feature is supported. -->
    <DisplayString Condition="_size == 0" Optional="true">()</DisplayString>
    <DisplayString Condition="_size == 1">(x={_items[0]})</DisplayString>
    <DisplayString Condition="_size == 2">(x={_items[0]}, y={_items[1]})</DisplayString>
    <DisplayString Condition="_size == 3">(x={_items[0]}, y={_items[1]}, z={_items[2]})</DisplayString>
    <DisplayString>[Size={_size,x}] (x={_items[0]}, y={_items[1]}, z={_items[2]}, ...)</DisplayString>

    <!-- Included to show the <StringView> feature is supported. -->
    <StringView Condition="true" Optional="true">_stringViewText</StringView>

    <Expand HideRawView="false">
      <!-- Included to show the <Item> feature is supported. -->
      <Item Name="X" Condition="_size &lt; 4 &amp;&amp; _size &gt;= 1" Optional="true">_items[0]</Item>
      <Item Name="Y" Condition="_size &lt; 4 &amp;&amp; _size &gt;= 2" Optional="true">_items[1]</Item>
      <Item Name="Z" Condition="_size &lt; 4 &amp;&amp; _size &gt;= 3" Optional="true">_items[2]</Item>

      <!-- Included to show the <ArrayItems> feature is supported. -->
      <ArrayItems Condition="_size >= 4" Optional="true">
        <Size Condition="true" Optional="true">_size</Size>
        <ValuePointer Condition="true">_items</ValuePointer>
      </ArrayItems>

      <!-- Included to show the <IndexListItems> feature is supported. -->
      <IndexListItems Condition="true" Optional="true">
        <Size Condition="true" Optional="true">_listSize</Size>
        <ValueNode Condition="true">_list[%i]</ValueNode>
      </IndexListItems>

      <!-- Included to show the <LinkedListItems> feature is supported. -->
      <LinkedListItems Condition="true" Optional="true">
        <Size Optional="true">_listSize</Size>
        <HeadPointer>_head</HeadPointer>
        <NextPointer>_next</NextPointer>
        <ValueNode>_value</ValueNode>
      </LinkedListItems>

      <!-- Included to show the <ExpandedItem> feature is supported. -->
      <ExpandedItem Condition="true" Optional="true">_childVar</ExpandedItem>

      <!-- Included to show the <Synthetic> feature is supported. -->
      <Synthetic Name="[Size]" Condition="true" Optional="true">
        <DisplayString>_size</DisplayString>
        <Expand HideRawView="true">
          <!-- Any supported <Expand> sub-tags. -->
        </Expand>
      </Synthetic>

      <!-- Included to show the <TreeItems> feature is supported. -->
      <TreeItems Condition="true" Optional="true">
        <Size>_treeSize</Size>
        <HeadPointer>_head</HeadPointer>
        <LeftPointer>_left</LeftPointer>
        <RightPointer>_right</RightPointer>
        <ValueNode>_value</ValueNode>
      </TreeItems>

      <!-- Included to show format specifiers are supported. -->
      <Item Name="[Hex Dump at {_index,x}]">myInt[_index],x</Item>
    </Expand>
  </Type>
</AutoVisualizer>

Crea archivos de Natvis

En Visual Studio, se permite que crees tus propios archivos de Natvis. Más información sobre cómo personalizar las ventanas de variables del depurador, consulta MSDN.

Depura los archivos de Natvis

En algunos casos, los errores se presentarán como el valor de una variable (p. ej., en las ventanas Auto, Watch, etc.). Por ejemplo: <error: use of undeclared identifier 'missingVar'>.

Para acceder a información detallada sobre el error, abre el archivo GoogleAndroid.log desde la barra de herramientas de Android Game Development Extension.

Limitaciones conocidas

  • Si tu etiqueta o atributo no aparece en el archivo de ejemplo anterior, quiere decir que actualmente no es compatible. Visual Studio ignora las etiquetas y los atributos no compatibles, por lo que, si lo dejas en un archivo de Natvis existente, este archivo funcionará, siempre que use nuestro esquema.

  • El atributo Usage, a pesar de que el esquema lo requiere, no es compatible con <SmartPointer>. Sin embargo, LLDB no restringe el acceso a los operadores definidos en C++. Por lo tanto, cualquier operador requerido puede definirse en C++ en su lugar.