RaspberryPi[72] gcc デバッグ用コンパイルオプション整理(備忘)

経緯

Raspberry Pi(Linux)上で C プログラムをデバッグする際に、
gcc のオプションを段階的に追加して不具合を特定したときのメモ。

主に gdb / AddressSanitizer(ASan) を使った。

基本のデバッグビルド

-g -O0 -Wall -Wextra -Wformat

-g
→ デバッグシンボルを付与(gdb 用)

-O0
→ 最適化無効(変数が消えたり並び替えられるのを防ぐ)

-Wall -Wextra
→ 警告をできるだけ出す

-Wformat
→ printf / fprintf の引数不一致を警告

※ デバッグ時は -O1 以上は避けるのが基本。

AddressSanitizer(ASan)でメモリ破壊検出

スタック破壊・配列オーバーラン・use-after-free の検出に使用。

-fsanitize=address -g -O0

実際のビルド例:

gcc xing_alart_lte.c \
  -fsanitize=address -g -O0 \
  -Wall -Wextra -Wformat \
  -o xing_alart_lte

ASan で検出できた例:

・stack-buffer-overflow

・配列の underflow / overflow

・NULL ポインタ参照の兆候

ASan の出力は 行番号と変数名まで出るので非常に強力。

ASan 使用時の注意点(重要)

・実行が遅くなる

・実行速度は体感で 2〜5倍程度遅くなる

・常時運用には向かない

・ASan デバッグ中は 手動実行

ASan はデバッグ専用 最終的な運用バイナリでは 必ず外す。

Coreを吐いたとき基本コマンド

gdb ./xing_alart_lte core

よく使ったコマンド:

bt
bt full
frame 0
info locals
info args

bt
→ どこで落ちたか(最重要)

bt full
→ ローカル変数の中身も確認

info locals
→ そのフレームの変数一覧

まとめ

用途オプション
gdb デバッグ-g -O0
警告強化-Wall -Wextra -Wformat
メモリ破壊検出-fsanitize=address
本番運用ASan を外す