エラー: heap-use-after-free

Address Sanitizer エラー: 割り当て解除されるメモリの使用

ここでは、ヒープ内のストレージを mallocrealloc (c)、new (C++) を使用して割り当てられる 3 つの例を、volatile の誤使用とともに示します。

例- malloc

// example1.cpp
// heap-use-after-free error
#include <stdlib.h>

int main() {
  char *x = (char*)malloc(10 * sizeof(char));
  free(x);

  // ...

  return x[5];   // Boom!
}

この例をビルドしてテストするには、Visual Studio 2019 バージョン 16.9 以降の開発者コマンド プロンプトで次のコマンドを実行します。

cl example1.cpp /fsanitize=address /Zi
devenv /debugexe example1.exe

Visual Studio が表示されたら、 F5 を押して例 1 を実行します。

結果のエラー

割り当て解除されたメモリ エラーの使用を示すデバッガーのスクリーンショット (例: 1)。

スローされた例外ダイアログは 11 行目を指し、x [ 5] を返します。"アドレスサニタイザー エラー 割り当て解除されたメモリの使用" と表示されます。 スクリーンショットに示されていないのは、メモリ アドレスを示すコンソール ウィンドウの出力と、アドレス指定可能なバイト、部分的にアドレス指定可能なバイト、解放されたヒープ領域、およびエラー領域のヒープ左赤ゾーン バイトを識別するためのキーです。

例- operator new

// example2.cpp
// heap-use-after-free error
#include <windows.h>

int main() {
  char *buffer = new char[42];
  delete [] buffer;

  // ...

  buffer[0] = 42;  // Boom!
  return 0;
}

この例をビルドしてテストするには、Visual Studio 2019 バージョン 16.9 以降の開発者コマンド プロンプトで次のコマンドを実行します。

cl example2.cpp /fsanitize=address /Zi
devenv /debugexe example2.exe

Visual Studio が表示されたら、 F5 を押して例 2 を実行します。

結果のエラー: operator new

例 2 の割り当て解除されたメモリ エラーの使用を示すデバッガーのスクリーンショット。

スローされた例外ダイアログは、11 行目の buffer[0] = 42 を指し、「アドレスサニタイザー エラー: 割り当て解除されたメモリの使用」と表示されます。 スクリーンショットに示されていないのは、メモリ アドレスを示すコンソール ウィンドウの出力と、アドレス指定可能なバイト、部分的にアドレス指定可能なバイト、解放されたヒープ領域、およびヒープを識別するためのキーです。エラーの領域に alloca red zone bytes が残っています。

例- realloc

// example3.cpp
// heap-use-after-free error
#include <malloc.h>

int main() {
  char *buffer = (char*)realloc(0, 42);
  free(buffer);

  // ...

  buffer[0] = 42;  // Boom!
  return 0;
}

この例をビルドしてテストするには、Visual Studio 2019 バージョン 16.9 以降の開発者コマンド プロンプトで次のコマンドを実行します。

cl example3.cpp /fsanitize=address /Zi
devenv /debugexe example3.exe

Visual Studio が表示されたら、 F5 を押して例 3 を実行します。

結果のエラー: realloc

例 3 の割り当て解除されたメモリ エラーの使用を示すデバッガーのスクリーンショット。

スローされた例外ダイアログは、11 行目の buffer[0] = 42 を指し、「アドレスサニタイザー エラー: 割り当て解除されたメモリの使用」と表示されます。 スクリーンショットに示されていないのは、メモリ アドレスを示すコンソール ウィンドウの出力と、アドレス指定可能なバイト、部分的にアドレス指定可能なバイト、解放されたヒープ領域、およびエラー領域のヒープ左赤ゾーン バイトを識別するためのキーです。

例: volatile

// example4.cpp
// heap-use-after-free error
#include <stdlib.h>

int main() {

  volatile char *x = (char*)malloc(sizeof(char));
  free((void*)x);

      //...

  *x = 42;        // Boom!
}

この例をビルドしてテストするには、Visual Studio 2019 バージョン 16.9 以降の開発者コマンド プロンプトで次のコマンドを実行します。

cl example4.cpp /fsanitize=address /Zi
devenv /debugexe example4.exe

Visual Studio が表示されたら、 F5 を押して例 4 を実行します。

結果のエラー: volatile

例 4 の割り当て解除されたメモリ エラーの使用を示すデバッガーのスクリーンショット。

スローされた例外ダイアログは、12 行目 *x = 42 行目を指し、「アドレスサニタイザー エラー: 割り当て解除されたメモリの使用」と表示されます。 スクリーンショットに示されていないのは、メモリ アドレスを示すコンソール ウィンドウの出力と、アドレス指定可能なバイト、ヒープの左の赤いゾーン バイト、およびエラーの領域内のアドレス指定可能で部分的にアドレス指定可能なバイトを識別するためのキーです。

関連項目

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