اشکال زدا

هنگام استفاده از برنامه افزودنی توسعه بازی اندروید، پروژه خود را با Visual Studio Debugger (LLDB) اشکال زدایی کنید.

دیباگر را اجرا کنید

قبل از اینکه بتوانید دیباگر را اجرا کنید، باید بتوانید بازی خود را در اندروید بسازید، اجرا و اجرا کنید. برای جزئیات بیشتر به بخش Run the sample مراجعه کنید.

هنگامی که مطمئن شدید که می توانید بازی خود را بدون دیباگر اجرا کنید، می توانید با فشار دادن F5 یا انتخاب آیتم Start Debugging در منوی Debug از دیباگر استفاده کنید. هنگامی که دیباگر به بازی متصل می شود، باید یک دیالوگ ببینید.

راه اندازی دیباگر بین 10 ثانیه تا 1 دقیقه یا بیشتر طول می کشد، بسته به اندازه برنامه شما و تعداد نمادهایی که باید در هنگام راه اندازی بارگذاری شوند. زمانی که برای اولین بار به یک دستگاه جدید متصل می‌شوید، زمان بیشتری طول می‌کشد، زیرا دیباگر باید تعدادی کتابخانه اندروید را از دستگاه به دستگاه میزبان دانلود کند. اگر در اولین تلاش شما با یک دستگاه جدید بیش از 1 دقیقه طول می کشد، جلسه اشکال زدایی را لغو کرده و سپس آن را مجدداً راه اندازی کنید.

وقتی دیباگر را به این صورت اجرا می کنید، بازی در حالت Waiting for Debugger شروع می شود و تا زمانی که دیباگر وصل نشود، هیچ کد بازی شما را اجرا نمی کند. این به شما امکان می دهد بخش اولیه بازی خود را نیز اشکال زدایی کنید.

با مطالعه مستندات ویژوال استودیو می توانید اطلاعات بیشتری در مورد ویژگی های خاص دیباگر ویژوال استودیو بیابید.

پیوست کردن به یک فرآیند

اگر می‌خواهید بازی‌ای را که قبلاً روی یک دستگاه فیزیکی یا مجازی اجرا می‌شود، اشکال‌زدایی کنید، می‌توانید اشکال‌زدایی را از ویژوال استودیو به فرآیند متصل کنید.

در ویژوال استودیو، مطمئن شوید که یک راه حل اندروید باز است و:

  1. به منوی Debug رفته و گزینه Attach to Process را انتخاب کنید.
  2. از منوی کشویی Transport ، افزونه توسعه بازی اندروید را انتخاب کنید.
  3. از منوی کشویی Qualifier ، دستگاه Android خود را انتخاب کنید.
  4. فرآیند بازی را از لیست فرآیندهای موجود انتخاب کنید و روی Attach کلیک کنید.

پیوست به پردازش

اجرای دستورات LLDB.Shell

با فعال بودن یک جلسه اشکال زدایی، از پنجره فرمان ویژوال استودیو برای اجرای دستورات LLDB.Shell استفاده کنید.

فرمت فرمان:

LLDB.Shell [command]

مثال:

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

تجسم داده ها

تعیین کننده های قالب

می‌توانید با استفاده از مشخص‌کننده‌های قالب، قالبی را که در آن یک مقدار در پنجره‌های Autos ، Locals ، Watch و متغیر DataTip نمایش داده می‌شود، تغییر دهید.

مشخص کننده های قالب در انتهای عبارات یافت می شوند. آنها با یک کاما و سپس یک رشته کوتاه شروع می شوند. برای مثال، مشخص‌کننده ,x در عبارت _myInt,x myInt را به صورت حروف کوچک هگزادسیمال قالب‌بندی می‌کند.

مشخص‌کننده‌های قالب را می‌توان مستقیماً در پنجره Watch یا در پنجره‌های Autos ، Locals و DataTip با افزودن آنها به عبارات Natvis خود استفاده کرد. برای اطلاعات بیشتر به Natvis مراجعه کنید.

لیست مشخص کننده های پشتیبانی

نام قالب مشخص کننده(های) توضیحات
بولی ب با استفاده از قانون مرسوم که 0 نادرست است و بقیه چیزها درست است، این را به عنوان یک بولی درست/نادرست نشان دهید.
باینری ب این را به صورت دنباله ای از بیت ها نشان دهید
باینری، بدون 0b پیشرو bb این را به صورت دنباله ای از بیت ها بدون پیشوند 0b نشان دهید
بایت ها y بایت ها را نشان دهید، اما سعی کنید آنها را به صورت کاراکترهای ASCII نیز نمایش دهید
به عنوان مثال (int *) c.sp.x = 50 f8 bf 5f ff 7f 00 00 P.._....
بایت با اسکی Y بایت ها را نشان دهید، اما سعی کنید آنها را به صورت کاراکترهای ASCII نیز نمایش دهید
به عنوان مثال (int *) c.sp.x = 50 f8 bf 5f ff 7f 00 00 P.._....
شخصیت ج بایت ها را به صورت کاراکترهای اسکی نشان دهید
به عنوان مثال (int *) c.sp.x = P\xf8\xbf_\xff\x7f\0\0
کاراکتر قابل چاپ سی بایت ها را به صورت کاراکترهای اسکی قابل چاپ نشان دهید
به عنوان مثال (int *) c.sp.x = P.._....
شناور پیچیده اف این مقدار را به عنوان بخش واقعی و خیالی یک عدد ممیز شناور پیچیده تفسیر کنید
به عنوان مثال (int *) c.sp.x = 2.76658e+19 + 4.59163e-41i
اعشاری د، من این را به‌عنوان یک عدد صحیح علامت‌دار نشان دهید (این یک cast را انجام نمی‌دهد، فقط بایت‌ها را به عنوان یک عدد صحیح با علامت نشان می‌دهد)
شمارش E,en این را به صورت شمارش نشان دهید، در صورت موجود بودن نام مقدار یا مقدار صحیح را در غیر این صورت چاپ کنید
به عنوان مثال (enum enumType) val_type = eValue2
هگزادسیمال - کوچک x، h این را با حروف کوچک هگزا دسیمال نشان دهید (این کار cast را انجام نمی دهد، فقط بایت ها را به صورت هگز نشان می دهد)
هگزادسیمال - بزرگ X، H این را با حروف هگزادسیمال بزرگ نشان دهید (این کار cast را انجام نمی دهد، فقط بایت ها را به صورت هگزا نشان می دهد)
هگزادسیمال - حروف کوچک، بدون 0x پیشرو xb، hb این را با حروف کوچک هگزا دسیمال بدون پیشوند 0x نشان دهید (این کار cast را انجام نمی دهد، فقط بایت ها را به صورت هگزا نشان می دهد)
هگزادسیمال - بزرگ، بدون 0x پیشرو Xb، Hb این را با علامت هگزادسیمال بزرگ و بدون پیشوند 0x نشان دهید (این کار cast را انجام نمی دهد، فقط بایت ها را به صورت هگزا نشان می دهد)
شناور f این عدد را به‌عنوان یک عدد ممیز شناور نشان دهید (این یک cast را انجام نمی‌دهد، بلکه صرفاً بایت‌ها را به عنوان یک مقدار ممیز شناور IEEE754 تفسیر می‌کند)
هشتی o این را با نماد هشتی نشان دهید
نوع سیستم عامل O این را به عنوان یک MacOS OSType نشان دهید
به عنوان مثال (شناور) x = '\n\x1f\xd7\n'
رشته - رشته C س این را به عنوان یک رشته C با 0 خاتمه نشان دهید
به عنوان مثال "سلام دنیا"
رشته - رشته C، بدون علامت نقل قول sb این را به عنوان یک رشته C خاتمه یافته بدون علامت نقل قول نشان دهید،
به عنوان مثال سلام دنیا
رشته - UTF-8 s8 این را به عنوان یک رشته UTF-8 با 0 خاتمه نشان دهید
به عنوان مثال u8 "سلام دنیا ☕"
رشته - UTF-8، بدون علامت نقل قول s8b این را به عنوان یک رشته UTF-8 با 0 خاتمه بدون علامت نقل قول نشان دهید
مثلا سلام دنیا ☕
رشته - UTF-16 سو این را به عنوان یک رشته UTF-16 با 0 خاتمه نشان دهید
به عنوان مثال تو "سلام دنیا ☕"
رشته - UTF-16، بدون علامت نقل قول فرعی این را به عنوان یک رشته UTF-16 با 0 خاتمه بدون علامت نقل قول نشان دهید
مثلا سلام دنیا ☕
رشته - UTF-32 s32 این را به عنوان یک رشته UTF-32 با 0 خاتمه نشان دهید
به عنوان مثال "سلام دنیا ☕"
رشته - UTF-32، بدون علامت نقل قول s32b این را به عنوان یک رشته UTF-32 با 0 خاتمه بدون علامت نقل قول نشان دهید
مثلا سلام دنیا ☕
یونیکد 16 U این را به صورت کاراکتر UTF-16 نشان دهید
به عنوان مثال (شناور) x = 0xd70a 0x411f
یونیکد 32 U32 این را به صورت نویسه UTF-32 نشان دهید
به عنوان مثال (شناور) x = 0x411fd70a
اعشاری بدون علامت تو این را به عنوان یک عدد صحیح بدون علامت نشان دهید (این یک cast را انجام نمی دهد، فقط بایت ها را به عنوان یک عدد صحیح بدون علامت نشان می دهد)
اشاره گر ص این را به عنوان یک اشاره گر بومی نشان دهید (مگر اینکه واقعاً یک اشاره گر باشد، آدرس حاصل احتمالاً نامعتبر خواهد بود)
عدد صحیح مختلط من این مقدار را به عنوان بخش واقعی و خیالی یک عدد صحیح مختلط تفسیر کنید
به عنوان مثال (int *) اشاره گر = 1048960 + 1i
آرایه کاراکتر الف این را به صورت آرایه ای از کاراکترها نشان دهید
به عنوان مثال (char) *c.sp.z = {X}
خام ! فرمت خام، بدون توجه به سفارشی سازی نماهای نوع داده

ناتویس

چارچوب Natvis به شما این امکان را می دهد تا نحوه نمایش انواع بومی را در پنجره های متغیر دیباگر، ویژوال استودیو سفارشی کنید. به عنوان مثال، از Natvis برای سفارشی کردن نمایشگرها برای پنجره‌های Watch ، Locals و Data Tips استفاده کنید.

ویژگی Natvis به طور پیش‌فرض فعال است، اما می‌توان آن را از Visual Studio با تنظیم Tools > Options > Android Game Development Extension > Natvis flag روی Disabled غیرفعال کرد.

در حال بارگیری فایل های Natvis

ویژوال استودیو فایل‌های Natvis را از سه مکان ذکر شده در زیر بارگیری می‌کند و هر بار که جلسه اشکال‌زدایی را شروع می‌کنید، آنها را دوباره بارگیری می‌کند. فایل ها باید به طرح Natvis Visual Studio 2017 پایبند باشند.

  • فایل های .natvis که بخشی از یک پروژه بارگذاری شده یا مورد راه حل سطح بالا هستند.
  • فهرست راهنمای کاربر ( %USERPROFILE%\Documents\Visual Studio 2017\Visualizers )
  • دایرکتوری سراسر سیستم ( %VSINSTALLDIR%\Common7\Packages\Debugger\Visualizers )
بارگذاری مجدد فایل های Natvis

با ارزیابی .natvisreload در پنجره Command یا Watch، فایل‌های Natvis را در طول جلسه اشکال‌زدایی بارگیری مجدد کنید.

نمونه فایل Natvis

این نمونه فایل Natvis شامل تمام برچسب ها و ویژگی هایی است که در حال حاضر پشتیبانی می شوند.

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

تالیف فایل های Natvis

ویژوال استودیو از نوشتن فایل‌های Natvis خود پشتیبانی می‌کند. برای اطلاعات بیشتر در مورد سفارشی کردن پنجره های متغیر اشکال زدا، MSDN را ببینید.

اشکال زدایی فایل های Natvis

در برخی موارد خطاها به عنوان مقدار یک متغیر نمایش داده می شوند (مثلاً در پنجره های خودکار ، تماشا ، و غیره). به عنوان مثال: <error: use of undeclared identifier 'missingVar'>

می‌توانید با باز کردن فایل GoogleAndroid.log از نوار ابزار توسعه بازی Android Extension، به جزئیات بیشتری در مورد خطا دسترسی پیدا کنید.

محدودیت های شناخته شده

  • اگر برچسب یا ویژگی شما در فایل مثال بالا فهرست نشده است، در حال حاضر پشتیبانی نمی شود. ویژوال استودیو تگ‌ها و ویژگی‌های پشتیبانی‌نشده را نادیده می‌گیرد، بنابراین می‌توانید آن‌ها را در یک فایل Natvis موجود بگذارید و فایل تا زمانی که از طرح ما استفاده کند کار خواهد کرد.

  • ویژگی Usage ، اگرچه توسط طرح مورد نیاز است، برای <SmartPointer> پشتیبانی نمی شود. با این حال، LLDB دسترسی به اپراتورهای تعریف شده در C++ را محدود نمی کند، به طوری که هر عملگر مورد نیاز را می توان در C++ تعریف کرد.