Debugger

Debug project Anda dengan Debugger Visual Studio (LLDB) saat menggunakan Android Game Development Extension.

Menjalankan debugger

Sebelum dapat menjalankan debugger, Anda harus dapat membuat, men-deploy, dan menjalankan game di Android. Lihat bagian Menjalankan contoh untuk detailnya.

Setelah yakin dapat menjalankan game tanpa debugger, Anda dapat menggunakan debugger dengan menekan F5 atau memilih item Start Debugging di menu Debug. Anda akan melihat dialog saat debugger dipasang ke game.

Meluncurkan debugger memerlukan waktu antara 10 detik hingga 1 menit atau lebih, bergantung pada ukuran aplikasi Anda dan jumlah simbol yang perlu dimuat saat dimulai. Lebih banyak waktu diperlukan saat memasang debugger ke perangkat baru untuk pertama kalinya karena harus mendownload beberapa library Android dari perangkat ke mesin host. Jika upaya pertama dengan perangkat baru memakan waktu lebih dari 1 menit, pertimbangkan untuk membatalkan sesi debug, lalu memulai ulang.

Saat Anda menjalankan debugger dengan cara ini, game dimulai dalam mode Waiting for Debugger dan tidak akan menjalankan kode game apa pun hingga debugger terhubung. Ini juga memungkinkan Anda untuk men-debug bagian inisialisasi game.

Anda dapat menemukan informasi selengkapnya tentang fitur debugger Visual Studio tertentu dengan membaca Dokumentasi Visual Studio.

Memasang ke proses

Jika ingin men-debug game yang sudah berjalan di perangkat fisik atau virtual, Anda dapat memasang debugger ke proses dari Visual Studio.

Di Visual Studio, pastikan solusi Android terbuka, lalu:

  1. Buka menu Debug dan pilih Attach to Process....
  2. Dari dropdown Transport, pilih Android Game Development Extension.
  3. Dari dropdown Qualifier, pilih perangkat Android Anda.
  4. Pilih proses game dari daftar proses yang tersedia dan klik Attach.

Pasang ke proses

Mengeksekusi perintah LLDB.Shell

Dengan sesi proses debug aktif, gunakan Command Window Visual Studio untuk menjalankan perintah LLDB.Shell.

Format perintah:

LLDB.Shell [command]

Contoh:

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

Visualisasi data

Penentu Format

Anda dapat mengubah format untuk menampilkan nilai di jendela Autos, Locals, Watch, dan DataTip variabel menggunakan penentu format.

Penentu format terdapat di akhir ekspresi. Penentu format dimulai dengan koma yang diikuti dengan string pendek. Misalnya, penentu ,x dalam ekspresi _myInt,x akan memformat myInt sebagai heksadesimal huruf kecil.

Penentu format dapat digunakan langsung di jendela Watch atau Autos, Locals, dan DataTip dengan menambahkannya ke ekspresi Natvis. Lihat Natvis untuk informasi selengkapnya.

Daftar penentu dukungan

Nama Format Penentu Deskripsi
boolean B tampilkan ini sebagai boolean benar/salah, menggunakan aturan kebiasaan bahwa 0 adalah salah dan yang lainnya benar
biner b tampilkan ini sebagai urutan bit
biner, tanpa awalan 0b bb tampilkan ini sebagai urutan bit tanpa awalan 0b
byte y tampilkan byte, tetapi coba tampilkan juga sebagai karakter ASCII
mis. (int *) c.sp.x = 50 f8 bf 5f ff 7f 00 00 P.._....
byte dengan ASCII Y tampilkan byte, tetapi coba tampilkan juga sebagai karakter ASCII
mis. (int *) c.sp.x = 50 f8 bf 5f ff 7f 00 00 P.._....
karakter c tampilkan byte sebagai karakter ASCII
mis. (int *) c.sp.x = P\xf8\xbf_\xff\x7f\0\0
karakter yang dapat dicetak C tampilkan byte sebagai karakter ASCII yang dapat dicetak
mis. (int *) c.sp.x = P.._....
float kompleks F tafsirkan nilai ini sebagai bagian nyata dan khayalan dari bilangan floating point kompleks
mis. (int *) c.sp.x = 2.76658e+19 + 4.59163e-41i
desimal d, i tampilkan ini sebagai bilangan bulat bertanda (ini tidak menjalankan cast, melainkan hanya menampilkan byte sebagai bilangan bulat dengan tanda)
enumerasi E,en tampilkan ini sebagai enumerasi, dengan mencetak nama nilai jika tersedia, atau nilai bilangan bulat jika tidak
mis. (enum enumType) val_type = eValue2
heksadesimal - huruf kecil x, h tampilkan ini dalam notasi heksadesimal huruf kecil (ini tidak menjalankan cast, melainkan hanya menampilkan byte sebagai heks)
heksadesimal - huruf besar X, H tampilkan ini dalam notasi heksadesimal huruf besar (ini tidak menjalankan cast, melainkan hanya menampilkan byte sebagai heks)
heksadesimal - huruf kecil, tanpa awalan 0x xb, hb tampilkan ini dalam notasi heksadesimal huruf kecil tanpa awalan 0x (ini tidak menjalankan cast, melainkan hanya menampilkan byte sebagai heks)
heksadesimal - huruf besar, tanpa awalan 0x Xb, Hb tampilkan ini dalam notasi heksadesimal huruf besar tanpa awalan 0x (ini tidak menjalankan cast, melainkan hanya menampilkan byte sebagai heks)
float f tampilkan ini sebagai bilangan floating point (ini tidak menjalankan cast, melainkan hanya menafsirkan byte sebagai nilai floating point IEEE754)
oktal o tampilkan ini dalam notasi oktal
jenis OS O tampilkan ini sebagai MacOS OSType
mis. (float) x = '\n\x1f\xd7\n'
string - string C s tampilkan ini sebagai string C yang diakhiri dengan 0
mis. "halo dunia"
string - string C, tanpa tanda petik sb tampilkan ini sebagai string C yang diakhiri dengan 0 tanpa tanda petik
mis. halo dunia
string - UTF-8 s8 tampilkan ini sebagai string UTF-8 yang diakhiri dengan 0
mis. u8"halo dunia ☕"
string - UTF-8, tanpa tanda petik s8b tampilkan ini sebagai string UTF-8 yang diakhiri dengan 0 tanpa tanda petik
mis. halo dunia ☕
string - UTF-16 su tampilkan ini sebagai string UTF-16 yang diakhiri dengan 0
mis. u"halo dunia ☕"
string - UTF-16, tanpa tanda petik sub tampilkan ini sebagai string UTF-16 yang diakhiri dengan 0 tanpa tanda petik
mis. halo dunia ☕
string - UTF-32 s32 tampilkan ini sebagai string UTF-32 yang diakhiri dengan 0
mis. U"halo dunia ☕"
string - UTF-32, tanpa tanda petik s32b tampilkan ini sebagai string UTF-32 yang diakhiri dengan 0 tanpa tanda petik
mis. halo dunia ☕
unicode16 U tampilkan ini sebagai karakter UTF-16
mis. (float) x = 0xd70a 0x411f
unicode32 U32 tampilkan ini sebagai karakter UTF-32
mis. (float) x = 0x411fd70a
desimal tidak bertanda u tampilkan ini sebagai bilangan bulat tidak bertanda (ini tidak menjalankan cast, melainkan hanya menampilkan byte sebagai bilangan bulat tidak bertanda)
pointer p tampilkan ini sebagai pointer native (kecuali jika ini benar-benar pointer, alamat yang dihasilkan mungkin tidak valid)
bilangan bulat kompleks I tafsirkan nilai ini sebagai bagian nyata dan khayalan dari bilangan bulat kompleks
mis. (int *) pointer = 1048960 + 1i
array karakter a tampilkan ini sebagai array karakter
mis. (char) *c.sp.z = {X}
Raw ! format raw, mengabaikan penyesuaian tampilan jenis data apa pun

Natvis

Framework Natvis memungkinkan Anda menyesuaikan cara Visual Studio menampilkan jenis native di jendela variabel debugger. Misalnya, gunakan Natvis untuk menyesuaikan tampilan jendela Watch, Locals, dan Data Tips.

Fitur Natvis diaktifkan secara default, tetapi dapat dinonaktifkan dari Visual Studio dengan menyetel tanda Tools > Options > Android Game Development Extension > Natvis ke Disabled.

Memuat file Natvis

Visual Studio memuat file Natvis dari tiga lokasi yang tercantum di bawah ini dan memuat ulang file tersebut setiap kali Anda memulai sesi proses debug. File harus mematuhi skema Natvis Visual Studio 2017.

  • File .natvis yang merupakan bagian dari item solusi level atas atau project yang dimuat.
  • Direktori khusus pengguna (%USERPROFILE%\Documents\Visual Studio 2017\Visualizers)
  • Direktori seluruh sistem (%VSINSTALLDIR%\Common7\Packages\Debugger\Visualizers)
Memuat ulang file Natvis

Muat ulang file Natvis selama sesi debug berlangsung dengan mengevaluasi .natvisreload di Command Window atau jendela Watch.

Contoh file Natvis

Contoh file Natvis ini mencakup semua tag dan atribut yang saat ini didukung.

<?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>

Menulis file Natvis

Visual Studio mendukung pembuatan otorisasi file Natvis Anda sendiri. Untuk mengetahui informasi selengkapnya tentang cara menyesuaikan jendela variabel debugger, lihat MSDN.

Men-debug file Natvis

Dalam beberapa kasus, error akan ditampilkan sebagai Value variabel (mis. di jendela Auto, Watch, dll.). Contoh: <error: use of undeclared identifier 'missingVar'>

Anda dapat mengakses detail selengkapnya tentang error tersebut dengan membuka file GoogleAndroid.log dari toolbar Android Game Development Extension.

Batasan umum

  • Jika tidak tercantum dalam contoh file di atas, berarti saat ini tag atau atribut Anda tidak didukung. Visual Studio mengabaikan tag dan atribut yang tidak didukung, sehingga Anda dapat membiarkannya dalam file Natvis yang ada dan file tersebut akan berfungsi, asalkan menggunakan skema kami.

  • Atribut Usage, meskipun diperlukan oleh skema, tidak didukung untuk <SmartPointer>. Namun, LLDB tidak membatasi akses ke operator yang ditentukan dalam C++, sehingga setiap operator yang diperlukan dapat ditentukan dalam C++.