rust-debugging について
rust-debugging は、GDB、LLDB、バックトレース、panic の切り分け、ログ、非同期タスクの調査による Rust プログラムのデバッグをエージェント向けに案内します。
主な機能
- 01Rust プリンターを使った GDB と LLDB
- 02panic のバックトレース設定
- 03panic パターンの切り分け
- 04dbg! と tracing の手法
- 05tokio-console による非同期タスク調査
活用シーン
- 01GDB または LLDB での Rust 値の確認
- 02panic のバックトレース取得
- 03本番環境でのクラッシュ調査
- 04停止中または遅い Tokio タスクの特定
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ mohitmishra786/ low-level-dev-skills --skill rust-debuggingインストール後、Claude Code で/rust-debuggingを入力して読み込まれたか確認します。
同梱ファイルreferences/rust-gdb-pretty-printers.md
詳細
Rust のデバッグ
目的
Rust プログラムをデバッグするための手順をエージェントに案内します。Rust 用の pretty-printer を使った GDB/LLDB、バックトレースの設定、パニックのトリアージ、tokio-console を使った非同期処理のデバッグ、#[no_std] のデバッグ戦略を扱います。
トリガー
- 「GDB/LLDB を使って Rust バイナリをデバッグするにはどうすればよいですか?」
- 「Rust のパニックから完全なバックトレースを取得するにはどうすればよいですか?」
- 「非同期 Rust/Tokio をデバッグするにはどうすればよいですか?」
- 「GDB で Rust の pretty-printer が機能しません」
- 「本番環境で Rust のパニックをデバッグするにはどうすればよいですか?」
- 「Rust で dbg! と tracing を使うにはどうすればよいですか?」
ワークフロー
1. デバッグ用にビルドする
# Debug build (default) — full debug info, no optimization
cargo build
# Release with debug info (for profiling real workloads)
cargo build --release --profile release-with-debug
# Or configure in Cargo.toml:
# [profile.release-with-debug]
# inherits = "release"
# debug = true
# Run directly
cargo run
cargo run -- arg1 arg2
2. Rust 用の pretty-printer を使った GDB
# Use rust-gdb wrapper (sets up pretty-printers automatically)
rust-gdb target/debug/myapp
# Or set up manually in ~/.gdbinit:
# python
# import subprocess, sys
# ...
Rust 用の一般的な GDB セッション:
# Basic
(gdb) break main
(gdb) run arg1 arg2
(gdb) next # step over
(gdb) step # step into
(gdb) continue
# Rust-aware inspection
(gdb) print my_string # Shows String content via pretty-printer
(gdb) print my_vec # Shows Vec elements
(gdb) print my_option # Shows Some(value) or None
(gdb) info locals
# Break on panic
(gdb) break rust_panic
(gdb) break core::panicking::panic
# Backtrace
(gdb) bt # Short backtrace
(gdb) bt full # Full with locals
3. Rust 用の pretty-printer を使った LLDB
# Use rust-lldb wrapper
rust-lldb target/debug/myapp
# Manual setup
lldb target/debug/myapp
(lldb) command script import /path/to/rust/lib/rustlib/etc/lldb_lookup.py
(lldb) command source /path/to/rust/lib/rustlib/etc/lldb_commands
一般的な LLDB セッション:
(lldb) b main::main
(lldb) r arg1 arg2
(lldb) n # next (step over)
(lldb) s # step into
(lldb) c # continue
(lldb) frame variable # show locals
(lldb) p my_string # print variable with pretty-printer
(lldb) bt # backtrace
(lldb) bt all # all threads
4. バックトレースの設定
# Short backtrace (default on panic)
RUST_BACKTRACE=1 ./myapp
# Full backtrace with all frames
RUST_BACKTRACE=full ./myapp
# With symbols (requires debug build or separate debug info)
RUST_BACKTRACE=full ./target/debug/myapp
# Capture backtrace programmatically
use std::backtrace::Backtrace;
let bt = Backtrace::capture();
eprintln!("{bt}");
リリースバイナリでは、デバッグシンボルを別ファイルに保持します:
# Build release with debug info
cargo build --release
objcopy --only-keep-debug target/release/myapp target/release/myapp.debug
strip --strip-debug target/release/myapp
objcopy --add-gnu-debuglink=target/release/myapp.debug target/release/myapp
5. パニックのトリアージ
// Set a custom panic hook for structured logging
use std::panic;
panic::set_hook(Box::new(|info| {
let backtrace = std::backtrace::Backtrace::force_capture();
eprintln!("PANIC: {info}");
eprintln!("{backtrace}");
// Log to file, send to Sentry, etc.
}));
よくあるパニックのパターン:
| パニックメッセージ | 考えられる原因 |
|---|---|
index out of bounds: the len is N but the index is M | 配列/vec の範囲外アクセス |
called Option::unwrap() on a None value | None に対する unwrap |
called Result::unwrap() on an Err value | エラーに対する unwrap |
attempt to subtract with overflow | 整数のアンダーフロー(デバッグビルド) |
assertion failed | assert! または assert_eq! の失敗 |
stack overflow | 無限再帰 |
アンワインドの代わりにクラッシュダンプを取得するには、リリース時に panic = "abort" を使用します。
6. dbg! マクロ
// dbg! prints file, line, value and returns the value
let result = dbg!(some_computation(x));
// prints: [src/main.rs:15] some_computation(x) = 42
// Chain multiple values
let (a, b) = dbg!((compute_a(), compute_b()));
// Inspect inside iterator chains
let sum: i32 = (0..10)
.filter(|x| dbg!(x % 2 == 0))
.map(|x| dbg!(x * x))
.sum();
7. tracing を使った構造化ログ
[dependencies]
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
use tracing::{debug, error, info, instrument, warn};
#[instrument] // Auto-traces function entry/exit with arguments
fn process(id: u64, data: &str) -> Result<(), Error> {
debug!("Processing item");
info!(item_id = id, "Started processing");
if data.is_empty() {
warn!(item_id = id, "Empty data");
return Err(Error::EmptyData);
}
error!(item_id = id, err = ?some_result, "Failed");
Ok(())
}
// Initialize in main
tracing_subscriber::fmt()
.with_env_filter("myapp=debug,warn")
.init();
# Control log levels at runtime
RUST_LOG=debug ./myapp
RUST_LOG=myapp::module=trace,warn ./myapp
8. tokio-console を使った非同期処理のデバッグ
[dependencies]
console-subscriber = "0.3"
tokio = { version = "1", features = ["full", "tracing"] }
// In main
console_subscriber::init();
# Install and run tokio-console
cargo install tokio-console
tokio-console # Connects to running Rust process at port 6669
tokio-console では、タスクの状態、waker のアクティビティ、ブロック中のタスク、poll の所要時間を確認できます。
GDB/LLDB のコマンドリファレンスと pretty-printer のセットアップについては、references/rust-gdb-pretty-printers.md を参照してください。
関連スキル
- デバッグ情報フラグとビルド設定については、
skills/rust/rustc-basicsを使用します - GDB の基礎については、
skills/debuggers/gdbを使用します - LLDB の基礎については、
skills/debuggers/lldbを使用します - メモリ安全性と未定義動作については、
skills/rust/rust-sanitizers-miriを使用します
コメント
Markdown 対応