🔥

GCC / LLVM Sanitizer の使い方

2022/08/06に公開

はじめに

メモリ関連のバグ(メモリリーク)を見つけるためのツールの一つである、GCCもしくはLLVMのSanitizerについての記事です。

使い方

使い方は至って簡単で、後述の用途に応じてコンパイルオプションを追加してビルドし、通常通り目的のプログラムを実行するだけです。

Memory Sanitizer

メモリ領域は確保したものの、プログラムで意図的に初期化されていないメモリへのアクセスを検出する場合に利用します。

void main() {
  auto *buff = new char[256];
  buff[0] = 1;
  std::cout << buff[1] << std::endl; // [1]は見初期化のためここでエラー検出
}

コンパイルオプションに以下を追加します。

-fsanitize=memory

(未初期化メモリをチェックする)

Address Sanitizer

これが一番よく使うパターンだと思いますが、例えば以下のようなdelete忘れによるメモリリークを検出するような場合に利用します。

void main() {
  auto *buff = new char[256]();
}

コンパイルオプションに以下を追加します。

-fsanitize=address

Thread Sanitizer

複数スレッドが同期・排他制御なしに同じメモリにアクセス(ライト中のリードなど)した場合を検出する場合に利用します。つまりスレッドのレースコンディションの検出です。

int data;

void* thread1(void* arg) {
  data++;
}

void* thread2(void* arg) {
  data--;
}

int main() {
    pthread_t handle[2];

    pthread_create(&handle[0], NULL, thread1, NULL);
    pthread_create(&handle[1], NULL, thread2, NULL);
    pthread_join(handle[0], NULL);
    pthread_join(handle[1], NULL);
}

コンパイルオプションに以下を追加します。

-fsanitize=thread

Discussion