Пошаговый отладчик для Rust: как дебажить код в 2024 году?
Выбор отладчика для Rust
Для Rust доступны два основных подхода к пошаговой отладке:
- Терминальные отладчики — GDB (GNU Debugger) и LLDB (LLVM Debugger). Работают из командной строки.
- Интегрированные отладчики — встроенные в VS Code, IntelliJ Rust, CLion. Наиболее удобны для новичков.
Я рекомендую начать с VS Code + CodeLLDB — это самый простой и стабильный вариант. Но если вы фанат терминала, покажу и GDB.
Способ 1: VS Code + CodeLLDB (рекомендую)
Шаг 1. Установите расширение
Откройте VS Code, перейдите во вкладку Extensions (Ctrl+Shift+X) и установите CodeLLDB от Vadim Chugunov.
Шаг 2. Настройте конфигурацию запуска
Создайте файл .vscode/launch.json в корне проекта. Вставьте:
{
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"request": "launch",
"name": "Debug Rust",
"cargo": {
"args": ["build", "--bin", "название_вашего_бина"]
},
"args": [],
"cwd": "${workspaceFolder}"
}
]
}
Шаг 3. Поставьте точку останова
Кликните слева от номера строки в редакторе — появится красный кружок. Например, поставьте его на строке let discount = calculate_discount(&o);.
Шаг 4. Запустите отладку
Нажмите F5. VS Code соберёт проект в debug-режиме и остановится на точке останова. Теперь вы можете:
- Нажать F10 — шаг с обходом (не заходит в функцию)
- Нажать F11 — шаг с заходом (заходит в
calculate_discount) - Нажать Shift+F11 — выход из текущей функции
- Смотреть переменные в левой панели "VARIABLES"
- Наводить мышь на переменные в коде — всплывает значение
Способ 2: Терминальный отладчик GDB
Если вы предпочитаете командную строку:
Шаг 1. Установите GDB
Linux: sudo apt install gdb
macOS: brew install gdb (потребуется подписать сертификат)
Windows: установите через MSYS2 или WSL.
Шаг 2. Соберите с отладочной информацией
cargo build по умолчанию собирает debug-версию. Если нет — добавьте в Cargo.toml:
[profile.dev]
debug = true
Шаг 3. Запустите отладку
gdb target/debug/ваша_программа
Внутри GDB:
break process_orders— точка останова на функцииrun— запуск программыnext(илиn) — шаг с обходомstep(илиs) — шаг с заходомprint o— вывести значение переменнойbacktrace(илиbt) — стек вызововquit— выход
Советы для вашего конкретного случая
В вашем коде с process_orders цепочка итераторов — отладчик покажет каждую итерацию. Поставьте breakpoint внутри .map() и смотрите o на каждом шаге. Чтобы увидеть discount, зайдите в calculate_discount через F11.
Важно: Для блочных отладчиков в VS Code вы можете добавить watch expression — например, o.amount - discount — и смотреть, как меняется значение на каждой итерации.
Надеюсь, теперь отладка Rust перестанет быть для вас "слепым котёнком"!
<<Альтернатива: отладка через Rust Analyzer + breakpoints в коде
Если вы не хотите настраивать полноценный отладчик или работаете на удалённом сервере без GUI, есть лёгкий способ — использовать макрос std::dbg! в сочетании с eprintln! и условной компиляцией.
Но есть и более элегантный метод — библиотека inventory или самописный "отладчик" на основе макросов. Например:
macro_rules! debug_step {
($($arg:tt)*) => {
#[cfg(debug_assertions)]
{
eprintln!("[DEBUG] {}", format!($($arg)*));
// Имитация остановки: ждём Enter
let mut input = String::new();
std::io::stdin().read_line(&mut input).unwrap();
}
};
}
// Использование:
fn process_orders(orders: Vec<Order>) -> Vec<ProcessedOrder> {
orders.into_iter().filter(|o| {
debug_step!("Фильтр: order id={}, status={:?}", o.id, o.status);
o.status == OrderStatus::Pending
}).map(|o| {
debug_step!("Обработка order id={}", o.id);
// ...
}).collect()
}
Этот подход работает только в debug-режиме (без флага --release). Вы видите пошаговый вывод и нажимаете Enter, чтобы продолжить. Минус — нет просмотра стека вызовов, но для быстрой диагностики это спасает.
Для более продвинутого терминального опыта попробуйте rr (Record and Replay) от Mozilla — он записывает выполнение и позволяет шагать назад. Установка: cargo install rr. Запуск: rr record target/debug/программа, затем rr replay.