AddressSanitizer の既知の問題と制限事項

今後のリリースで期待する内容に関するフィードバックをお送りください。また、問題にぶつかった場合はバグを報告してください。

互換性のないオプションと機能

次のオプションと機能は、 /fsanitize=address と互換性がありません。無効または回避する必要があります。

標準ライブラリのサポート

Microsoft Visual C++ (MSVC) 標準ライブラリ (STL) は AddressSanitizer を部分的に使用し、他のコードの安全性チェックを提供します。 詳細については、「 container-overflow エラー」を参照してください。

注釈が無効になっている場合、またはそれらをサポートしていない標準ライブラリのバージョンでは、STL コードで発生した AddressSanitizer 例外によって、実際のバグが引き続き識別されます。 ただし、注釈が有効になっていて、それらをサポートする標準ライブラリのバージョンを使用している場合は、より正確です。

この例では、精度の欠如と注釈を有効にする利点を示します。

// Compile with: cl /fsanitize=address /Zi
#include <vector>

int main()
{   
    // Create a vector of size 10, but with a capacity of 20.    
    std::vector<int> v(10);
    v.reserve(20);

    // In versions prior to 17.2, MSVC ASan does NOT raise an exception here.
    // While this is an out-of-bounds write to 'v', MSVC ASan
    // ensures the write is within the heap allocation size (20).
    // With 17.2 and later, MSVC ASan will raise a 'container-overflow' exception:
    // ==18364==ERROR: AddressSanitizer: container-overflow on address 0x1263cb8a0048 at pc 0x7ff6466411ab bp 0x005cf81ef7b0 sp 0x005cf81ef7b8
    v[10] = 1;

    // Regardless of version, MSVC ASan DOES raise an exception here, as this write
    // is out of bounds from the heap allocation.
    v[20] = 1;
}

operator newのオーバーライドとdelete

AddressSanitizer (ASan) は、 operator newoperator delete のカスタム バージョンを使用して、 alloc_dealloc_mismatchなどの割り当てエラーを見つけます。 /INFERASANLIBSを使用してリンカーを実行して、ASan のnew/deleteオーバーライドの優先順位が低くなり、リンカーが ASan のカスタム バージョンよりも他のライブラリでoperator newまたはoperator deleteオーバーライドを選択できるようにします。 この場合、ASan はカスタム operator newoperator deleteに依存するいくつかのエラーをキャッチしない可能性があります。

MFC には、 operator newoperator deleteのカスタム オーバーライドが含まれています。 ASan が提供する operator newoperator deleteの代わりに Microsoft Foundation Classes (MFC) オーバーライドを使用すると、エラーが完全に見落とされたり、結果として誤って分類されたりする可能性があります。 次のエラーが見落とされたり、誤って分類されたりする可能性があります。

メモリ使用量

AddressSanitizer ランタイムは、メモリがすべて前もって割り当てられないように、実行中にメモリを OS に解放しません。 OS の視点から見ると、メモリ リークが発生しているように見えるかもしれません。

AddressSanitizer ランタイム DLL の場所

clang_rt.asan*.dll ランタイム ファイルは、コンパイラの横の %VSINSTALLDIR%\VC\Tools\MSVC\<version>\bin\<host-arch>\<target-arch>\ にインストールされます。 これらの場所は、デバッグ セッションと Visual Studio 開発者コマンド プロンプトのパスにあります。 これらのファイルは、C:\Windows\System32C:\Windows\SysWOW64 には置かれません。

カスタム プロパティ シートのサポート

Visual Studio プロパティ マネージャー ウィンドウでは、カスタム .props ファイルをプロジェクトに追加できます。 [AddressSanitizer の有効化] プロパティ (<EnableASAN>) が表示されている場合でも、ビルドではこのプロパティは使用されません。 .props値を使用して他のプロパティを設定するMicrosoft.cpp.propsの後にカスタム <EnableASAN> ファイルが含まれるため、ビルドではこれを優先しません。

回避策として、プロジェクトのルートに Directory.Build.props ファイルを作成し、 <EnableASAN> プロパティを定義します。 詳細については、「C++ ビルドのカスタマイズ」を参照してください。

スレッド ローカル変数

スレッド ローカル変数 ( __declspec(thread) または thread_local で宣言されたグローバル変数) は AddressSanitizer によって保護されません。 この制限は、Windows または Microsoft Visual C++ に固有のものではなく、一般的な制限事項です。

カスタム コードは、通常の関数の戻りシーケンスをスキップします

カスタム コードまたはアセンブリ言語を使用して、通常の戻りメカニズムを受け入れずに現在のスタック フレームから離れることはサポートされていません。 たとえば、長いジャンプで現在のスタック フレームを離れると、誤検知が発生する可能性があります。

代わりに、カスタムのジャンプのようなコードを呼び出す前に、 __asan_handle_no_return() を呼び出します。 この関数は、現在のスレッドのスタックに関連付けられているすべてのシャドウ バイトをクリアします。これにより、カバレッジが失われ、偽陰性のリスクが発生します。 ただし、古いスタック シャドウ バイトが原因で誤検知が発生することなく、プログラムはスタックを安全にアンワインドできます。

部分的にサニタイズされた実行可能ファイルに関する問題

プロセス内のすべてのコードが /fsanitize=addressでコンパイルされていない場合、ASan はすべてのメモリセーフ エラーを診断できない可能性があります。 最も一般的な例は、ASan でコンパイルされた DLL が、ASan でコンパイルされていないコードを含むプロセスに読み込まれる場合です。 この場合、ASan は、ASan 初期化の前に行われた割り当ての分類を試みます。 これらの割り当てが再割り当てされると、ASan はメモリの有効期間を所有および監視しようとします。

ASan でコンパイルされたすべての DLL がプロセスの終了前にプロセスからアンロードされた場合、 memcmpmemcpymemmoveなどのインターセプトされた関数への未解決の参照が原因でクラッシュする可能性があります。 最適な結果を得るには、 /fsanitize=addressでテスト対象のすべてのモジュールをコンパイルするか、プロセスに入った後に ASan でコンパイルされたモジュールをアンロードしないでください。

開発者コミュニティにバグを報告してください。

ASan 64 ビットの最初の確率例外

x64 では、MSVC ASan の シャドウ バイト 領域は数テラバイトの仮想アドレス空間を占有します。 ASan では、このメモリは事前コミットされません。 代わりに、オンデマンドページングが使用されます。 シャドウ ページに初めてアクセスすると、初回のページ フォールト例外が発生し、ページをコミットする ASan によって処理されます。

Visual Studio デバッガーはこれを適切に処理し、これらのトレースは表示しません。 ただし、WinDbgX などのデバッガーは、既定ではすべての例外で中断される可能性があります。 初回例外の中断を無効にすることをお勧めします。 たとえば、WinDbgX では、これは sxd av コマンドに対応します。

C++/CLI の ASan サポートは試験段階です

信頼性の高い AddressSanitizer (ASan) 診断の場合は、メモリセーフでないコードを、 /clr せずに /fsanitize=addressでコンパイルされたネイティブ翻訳単位または DLL で分離します。 C++/CLI ラッパーからネイティブ コードを呼び出します。

CLR はメモリと JIT で生成されたコードを管理するため、C++/CLI コードは ASan の読み込みを受信してインストルメンテーションを格納することは保証されません。 その結果:

  • C++/CLI および STL コード: C++/CLI メソッド内のメモリ アクセスは、STL コードによって実行されるアクセスを含め、インストルメント化されない場合があります。
  • マネージド配列: 範囲外のアクセスでは、ERROR: AddressSanitizer レポートではなく、 IndexOutOfRangeExceptionなどの CLR 動作が生成されます。
  • マネージド スレッド: C++/CLI メソッド本体内で出力されるネイティブ メモリ アクセスでは、ASan 診断が生成されない場合があります。
  • 最終処理とシャットダウン: 最終処理、プロセスのシャットダウン、または混合モードのアンロード中のレポートは、ユーザー コードのメモリバグを確実に示さない可能性があります。
  • ネイティブ ホスト: ネイティブ ホストから ASan 対応 C++/CLI ラッパー DLL を読み込むと、不明なアドレスのアクセス違反レポートなど、誤解を招くランタイム エラーが発生する可能性があります。

関連項目

AddressSanitizer の概要
AddressSanitizer のビルドと言語リファレンス
AddressSanitizer ランタイム リファレンス
AddressSanitizer シャドウ バイト
AddressSanitizer クラウドまたは分散テスト
AddressSanitizer デバッガーの統合
AddressSanitizer エラーの例