gcc で sanitizer を使う
tl;dr
$ gcc -fsanitize=undefined -fno-sanitize-recover=all foo.c $ UBSAN_OPTIONS='verbosity=1:abort_on_error=1:handle_abort=2:disable_coredump=0' ./a.out
詳細
gcc では asan (address sanitizer), ubsan (undefined behavior sanitizer) といった sanitizer が利用できる。 (clang でも利用可能。細かい違いは不明)
CFLAGS/CXXFLAGS, LDFLAGS の両方に -fsanitize=undefined
を付けると ubsan が有効になる。また、-fno-sanitize-recover=all
を付けると sanitizer 側でのエラー回復を無効化できる。単にコアダンプしてほしい場合などに有効。
さらに、sanitizer がエラーを報告する際の挙動を環境変数 ASAN_OPTIONS
, UBSAN_OPTIONS
で制御できる。書式は a=1:b=0:c=1
のように、<変数名>=<値>
をコロンで区切る。
変数は全 sanitizer 共通のものとそうでないものがある。今のところこれらに関するドキュメントがあまり見当たらないため、ソースを頑張って読むしかない模様:
- https://github.com/gcc-mirror/gcc/blob/master/libsanitizer/sanitizer_common/sanitizer_flags.inc
- https://github.com/gcc-mirror/gcc/blob/master/libsanitizer/ubsan/ubsan_flags.inc
有用そうな変数を挙げておく:
abort_on_error
: 1 でエラー落ちする際にabort()
を使う(デフォルトは_exit()
)。disable_coredump
: 0 でコアダンプする。64bit ではデフォルトで 1 になっている (巨大なコアを吐くのを防ぐためらしい)。 プログラム側でシグナルハンドラをいじっている場合、これを 0 にしてもコアダンプ しないことがある。その場合はhandle_abort
を併用する。handle_abort
: 2 でプログラム側での SIGABRT ハンドラ登録を禁止する。強制的に コアダンプさせるのに使える。verbosity
: 0 から 2 まで。1 以上のとき、UBSAN_OPTIONS
に無効なオプション が含まれていたらエラー落ちする際にその旨警告する。print_stacktrace
: UBSAN 用。1 でスタックトレースを吐く。