🔥
GCC / LLVM Sanitizer の使い方
はじめに
メモリ関連のバグ(メモリリーク)を見つけるためのツールの一つである、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