> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# XBOX での Address Sanitizer サポート

> XBOX での Address Sanitizer サポート

ほとんどの C++ プログラムと同様に、ゲームはプログラムの正当性および安定性に影響を与える一連のバグに悩まされる可能性があります。そのため、Visual Studio 2022 以降、Microsoft C/C++ コンパイラー (MSVC) と IDE は AddressSanitizer (ASan) 技術をサポートしています。これは、以下のような多くの発見が困難なバグを誤検知ゼロで検出する、コンパイラーおよびランタイムの技術です。

* Alloc/dealloc の不一致および new/delete 型の不一致
* ヒープに対して大きすぎる割り当て
* calloc オーバーフローおよび alloca オーバーフロー
* Double free と use after free
* グローバル変数のオーバーフロー
* ヒープ バッファー オーバーフロー
* アラインされた値の不正なアラインメント
* memcpy と strncat のパラメーター オーバーラップ
* スタック バッファー オーバーフローおよびアンダーフロー
* Stack use after return と use after scope
* ポイズニング後のメモリ使用

ASan の詳細については、Visual Studio ページを参照してください: [AddressSanitizer](https://learn.microsoft.com/cpp/sanitizers/asan) (Microsoft Docs)

## コンパイラーで ASan を有効にする

Address Sanitizer は Visual Studio プロジェクト システム、CMake ビルド システム、および IDE と統合されています。プロジェクトでは、追加のコンパイラー オプション *`/fsanitize=address`* を使用するか、Visual Studio でプロジェクト プロパティを設定することで AddressSanitizer を有効にできます。

<img src="https://mintcdn.com/microsoft-4404708b/ktEik-YaZoen6Rhy/images/gdk/tools/Address_Sanitizer_Project_Props.png?fit=max&auto=format&n=ktEik-YaZoen6Rhy&q=85&s=1717f26cc38c6cfdc96e683cb32752c0" alt="Visual Studio の ASan コンパイラー オプション" width="696" height="425" data-path="images/gdk/tools/Address_Sanitizer_Project_Props.png" />

<Note>このオプションは、x64 のすべての最適化レベルと構成に対応しています。ただし `edit-and-continue`、`incremental linking`、および `/RTC` とは**互換性がありません**。これらは ASan でコンパイルする前に無効にする必要があります。</Note>

ASan を有効にすると、追加のライブラリをコードにリンクする必要があります。この参照はビルド システムによって自動的に追加されます。プロジェクトの ***リンカー > 全般*** で「追加のライブラリ ディレクトリ」も設定する必要があります。以下のように、他のライブラリで使用されないように、`$(VC_LibraryPath_VC_x64)` の値が一覧の最後にあることを確認してください。

<img src="https://mintcdn.com/microsoft-4404708b/ktEik-YaZoen6Rhy/images/gdk/tools/Address_Sanitizer_Linker_Options.png?fit=max&auto=format&n=ktEik-YaZoen6Rhy&q=85&s=8f81ff7561ee160e16164518191f789b" alt="Visual Studio の ASan リンカー オプション" width="752" height="128" data-path="images/gdk/tools/Address_Sanitizer_Linker_Options.png" />

## ASan ランタイム要件

ゲームを ASan 有効でビルドすると、機能を有効化するために、実行時に追加の DLL が存在する必要があります。既定では、コンパイラーで ASan が有効になっていると、その DLL がプロジェクトの出力ディレクトリにコピーされ、実行可能ファイルと共にコンソールにデプロイされます。

必要に応じて、DLL は Visual Studio の `$(VC_ExecutablePath_x64)` ディレクトリ内で手動で見つけることができます。ビルド バージョンに応じて、XBOX では次のいずれかが必要です。

| DLL ファイル名                              | ビルド タイプ  |
| -------------------------------------- | -------- |
| `clang_rt.asan_dbg_dynamic-x86_64.dll` | デバッグ ビルド |
| `clang_rt.asan_dynamic-x86_64.dll`     | リリース ビルド |

## ランタイム デバッガー サポート

ASan を有効にしたゲームをデバッガーをアタッチした状態で実行すると、エラーが見つかった場合はデバッガーで中断し、エラーが発生した場所を特定できる詳細なレポートが表示されます。

一方、自動テスト フレームワークなどでデバッガーをアタッチせずに実行している場合、エラー情報は標準出力に表示され、ゲームは終了します。これは有用ですが、クラッシュの根本原因を特定するにはより多くの状態情報が必要な場合があります。そこで役立つのがクラッシュ ダンプ サポートです。

<Note>デバッガーをアタッチせずに実行し、その時点でシンボル解決が必要な場合、`llvm-symbolizer.exe` ファイルをゲーム EXE と一緒にデプロイする必要があります。このファイルは上記の ASan ランタイム DLL と同じ場所にあります。</Note>

## ランタイム クラッシュ ダンプ サポート

Visual Studio 16.9.8 または 16.10.2 以降、ASan はエラーに関連付けられたメタデータを含むクラッシュ ダンプ ファイルを保存するように構成できます。Visual Studio のデバッガーは、ダンプ ファイルに保存されたメタデータを解析し、クラッシュの追加コンテキストを提供します。ビルドごとにこのクラッシュ ダンプ保存を構成し、これらのバイナリ アーティファクトを保存して、適切なソース インデックスを備えた IDE で表示できます。

クラッシュ ダンプのドキュメントはこちらにあります:
[クラッシュ ダンプの構成](https://learn.microsoft.com/cpp/sanitizers/asan-offline-crash-dumps) (Microsoft Docs)

ただし、上記でリンクされているアプローチには環境変数の設定が必要で、これは XBOX ではサポートされていないため、代替方法が実装されました。XBOX タイトルにクラッシュ ダンプ サポートを追加するには、以下の 3 つの例のように、必要なクラッシュ ダンプ ファイル名情報を ASan に提供する関数コールバックを定義するだけで済みます。

<Note>ファイル名は通常、Visual Studio IDE の慣習に従って ***.dmp*** サフィックスを付けます。</Note>

```c++ theme={null}
// 1. Use a hardcoded dump name
extern "C" const wchar_t* __vcasan_save_dumps()
{
    return L"myCrashDump.dmp";
}

// 2. Programmatically build the dump name
extern "C" const wchar_t* __vcasan_save_dumps()
{
    return TestFramework.buildName + TestFramework.buildInfo + TestFramework.dateTime;
}

// 3. You can conditionally choose NOT to collect a crash dump
extern "C" const wchar_t* __vcasan_save_dumps()
{
    // Choose to create a crash dump based on a runtime flag
    if ( gCollectCrashDumps )
    {
        return L"myCrashDump.dmp";
    }
    else
    {
        // Returning NULL stops ASan creating a crash dump
        return NULL;
    };
}
```

この関数が返す名前について特定の要件はありませんが、コードが実行されるターゲット デバイス上の有効なファイル パスである必要があります。たとえば、クラッシュ ダンプをコンソールの D: ドライブに書き込めば、開発中に簡単に見つけて取得できます。

生成されるクラッシュ ダンプの種類を変更する機能も追加しました。プロセスが失敗したコール スタックを確認するには単純な「Triage」ダンプで十分な場合もありますが、一部の問題では発生時の周辺メモリが必要になる場合があります。この目的のため、XBOX プラットフォームでサポートされ、コンソールおよび xbWatson が生成するクラッシュ ダンプの種類と一致する 3 つの構成可能なクラッシュ ダンプ タイプを提供しています。

<Note>前の関数と同様に、このオーバーライドは XBOX では**任意**ですが、デバッガーをアタッチせずに ASan 情報を収集するためにクラッシュ ダンプを使用したい場合は強く推奨します。ダンプ ファイル名を提供したが、ダンプ タイプのオーバーライドを提供しなかった場合、XBOX で有効なクラッシュ ダンプを生成できません。</Note>

このコールバックは必要なダンプ タイプを示す数値を返します。有効なタイプは以下の例のとおりです。

```c++ theme={null}
extern "C" const signed int __vcasan_override_dumptype()
{
    // The current valid values are:
    // 0 : Triage Dump
    // 1 : Mini Dump
    // 2 : Heap Dump
    // Values outside this range are defaulted to 2 (Full Heap)

    // This example uses Heap Dumps which give the most information
    return 2;
}
```

## ASan コードの例

このコードは、これらの関数を既存のコードベースに簡単に追加し、必要に応じて調整する方法を示します。

```c++ theme={null}
#include <cstdio>

extern "C" const wchar_t* __vcasan_save_dumps()
{
    // Specify dump filename
    return L"myCrashDump.dmp";
}

extern "C" const signed int __vcasan_override_dumptype()
{
    // Full heap dump requested
    return 2;
}

static const int arraySize = 8;
static int asanArray[arraySize];
static int asanAccumulator = 0;

int main()
{
    // ASan should use the callback functions that we have provided
    for (int loop = 0; loop <= arraySize; loop++)
    {
        // We don't really care about accumulating the values
        // We just want to access outside the array causing an ASan error
        asanAccumulator += asanArray[loop];
    }

    // If we get here, we have failed as ASan should have caught the error above
    printf("fail");

    return 0;
}
```

以下のコマンド ラインでコードをコンパイルします。

```c++ theme={null}
cl /nologo /fsanitize=address /Zi ASanTest.cpp
```

このコードを実行すると、ASan 例外がスローされ、上記の関数で指定されたクラッシュ ダンプが生成されます。既存のコードベースにこれらの関数を統合し、ASan が有効なときに任意のクラッシュ ダンプを生成できます。

## 既知の問題

* Visual Studio 2019 (16.11) の ASan は Game OS と互換性がありません。

* ASan DLL は Game OS と互換性がなく、17.12 および 17.13 の初期リリースでは読み込みに失敗します。これは 17.12.6 および 17.13.3 で修正されています。

* Visual Studio 2022 で Game OS の ASan サポートに関する起動時クラッシュを引き起こす回帰は、17.14.29 および Visual Studio 2026 の 18.4.1 で修正されました。

* XBOX 上でデバッガー配下で実行しているとき、以下の例外メッセージが一定の間隔で発せられますが、無視して問題ありません。

```
Exception thrown at 0x00007FF8FCAAFCF6 (clang_rt.asan_dynamic-x86_64.dll) in game.exe: 0xE0736171: Access violation reading location 0x000017FF1F9E1250.
```
