C++ での gdb デバッグ入門
SEGV やハングの原因特定は gdb(Linux) / lldb(macOS) の出番。この 1 ページで「落ちた → 30 秒で原因の行を特定」までできるようになります。
1. ビルド時に -g を忘れない
$ g++ -std=c++17 -Wall -g -O0 main.cpp -o app # デバッグ用
$ g++ -std=c++17 -O2 -g main.cpp -o app # 最適化+行情報(Prod)
-g でシンボル/行番号情報が埋め込まれます。-O2 との併用も可能ですが、最適化で変数が消えたり inline されたりするので、まずは -O0 で追うのが楽。
2. 最短の使い方(対話モード)
$ gdb ./app
(gdb) run # 実行
Program received signal SIGSEGV, ...
(gdb) bt # バックトレース
#0 process(0x0) at main.cpp:42
#1 loop() at main.cpp:28
#2 main() at main.cpp:10
(gdb) frame 0 # 0 番目のフレームへ
(gdb) list # 周辺のコードを表示
(gdb) print p # 変数 p を表示
$1 = 0x0 # ← nullptr 確定!
SEGV → run → bt → frame N → print 変数。この 4 ステップで多くのクラッシュは解明できます。
3. ブレークポイント
(gdb) break main.cpp:42 # 行番号
(gdb) break my_class::method # 関数名(オーバーロードは番号選択)
(gdb) condition 1 i==100 # 条件付き(i が 100 の時だけ止まる)
(gdb) continue # 再開
(gdb) next # 1 行実行(関数は stepover)
(gdb) step # 1 行実行(関数に入る)
(gdb) finish # 現関数から脱出するまで実行
C++ メソッドは class::name の形で指定。テンプレートは具体化された名前を指定するので break func<int>。
4. STL コンテナの中身を見る
素の gdb だと std::vector の中身が _M_start = 0x5555... のように暗号的に表示されます。pretty-printer を入れると {1, 2, 3} と人間可読に。
# ~/.gdbinit に追記
python
import sys
sys.path.insert(0, '/usr/share/gcc/python')
from libstdcxx.v6.printers import register_libstdcxx_printers
register_libstdcxx_printers(None)
end
Ubuntu なら apt install libstdc++6-dbg で入る。Mac では lldb が最初から std::vector を可読表示します。
5. コアダンプから解析
$ ulimit -c unlimited # core ファイル生成を許可
$ ./app
Segmentation fault (core dumped)
$ gdb ./app core # 死後解析
(gdb) bt
(gdb) thread apply all bt # 全スレッドのトレース
6. マルチスレッドのデバッグ
(gdb) info threads # 全スレッド一覧
(gdb) thread 3 # 3 番のスレッドへ
(gdb) bt
(gdb) thread apply all bt # 一括で全スレッドのトレース
デッドロックの調査に必須。「全スレッドが同じ mutex で止まっている」等が一目で分かる。
7. よく使うコマンド早見表
| コマンド | 短縮 | 用途 |
run | r | 実行 |
break L | b L | ブレーク設定 |
continue | c | 再開 |
next | n | 行単位実行(step over) |
step | s | 行単位実行(step into) |
print x | p x | 変数表示 |
info locals | | ローカル変数一覧 |
watch x | | 変数が変わったら停止 |
quit | q | 終了 |
GUI で楽をしたい: VS Code + 「C/C++」拡張、または CLion / Qt Creator でほぼ同機能を GUI で使えます。コマンドで動く gdb の知識があると TUI / CI / リモートでも戦える。