互換性のないオプションと機能
次のオプションと機能は、 /fsanitize=address
と互換性がありません。無効または回避する必要があります。
-
/RTC
オプションは AddressSanitizer と互換性がないため、無効にする必要があります。 - インクリメンタル リンクはサポートされていないため、無効にする必要があります。
- エディットコンティニュ はサポートされていないため、無効にする必要があります。
- コルーチンは AddressSanitizer と互換性がなく、再開可能な関数がインストルメンテーションから除外されています。
- OpenMP はサポートされていないため、無効にする必要があります。
- マネージド C++ はサポートされていないため、無効にする必要があります。
- C++ AMP はサポートされていないため、無効にする必要があります。
- ユニバーサル Windows プラットフォーム (UWP) アプリケーションはサポートされていません。
- 特別なケース リスト ファイルはサポートされていません。
-
/fsanitize
address' なしでビルドされたプリコンパイル済みヘッダーはサポートされていません。
標準ライブラリのサポート
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;
}
演算子 new と delete のオーバーライド
AddressSanitizer (ASan) は、 operator new
と operator delete
のカスタム バージョンを使用して、 alloc_dealloc_mismatch
などの割り当てエラーを見つけます。
/INFERASANLIBS
を使用してリンカーを実行すると、ASan のnew
/delete
オーバーライドの優先順位が低くなります。これにより、リンカーは、ASan のカスタム バージョンよりも他のライブラリのoperator new
またはoperator delete
オーバーライドを選択できます。 この場合、ASan はカスタム operator new
と operator delete
に依存するいくつかのエラーをキャッチできない可能性があります。
MFC には、 operator new
と operator delete
のカスタム オーバーライドが含まれており、 alloc_dealloc_mismatch
などのエラーが見逃される可能性があります。
メモリ使用量
AddressSanitizer ランタイムは、メモリがすべて前もって割り当てられないように、実行中にメモリを OS に解放しません。 OS の視点から見ると、メモリ リークが発生しているように見えるかもしれません。
AddressSanitizer ランタイム DLL の場所
clang_rt.asan*.dll
ランタイム ファイルは、コンパイラの横の %VSINSTALLDIR%\VC\Tools\MSVC\<version>\bin\<host-arch>\<target-arch>\
にインストールされます。 これらの場所は、デバッグ セッションと Visual Studio 開発者コマンド プロンプトのパスにあります。 これらのファイルは、C:\Windows\System32
や C:\Windows\SysWOW64
には置かれません。
カスタム プロパティ シートのサポート
Visual Studio プロパティ マネージャー ウィンドウでは、カスタム .props
ファイルをプロジェクトに追加できます。
Enable Address Sanitizer プロパティ (<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 がプロセスの終了前にプロセスからアンロードされた場合、 memcmp
、 memcpy
、 memmove
などのインターセプトされた関数への未解決の参照が原因でクラッシュする可能性があります。 最適な結果を得るには、 /fsanitize=address
でテスト対象のすべてのモジュールをコンパイルするか、プロセスに入った後に ASan でコンパイルされたモジュールをアンロードしないでください。
開発者コミュニティにバグを報告してください。
関連項目
AddressSanitizer の概要
AddressSanitizer のビルドと言語リファレンス
AddressSanitizer ランタイム リファレンス
AddressSanitizer シャドウ バイト
AddressSanitizer クラウドまたは分散テスト
AddressSanitizer デバッガーの統合
AddressSanitizer エラーの例