Отладка

Техники и рекомендации по отладке плагинов на Rust и обработке ошибок в процессе разработки языкового модуля.

Отладка — важная часть разработки плагинов на Rust для Plugify. Это руководство содержит подробные техники и инструменты для эффективной отладки плагинов на Rust.

Необходимые компоненты

Перед отладкой ваших плагинов на Rust убедитесь, что у вас есть следующее:

  • Установленный тулчейн Rust (rustc, cargo)
  • Отладчик: GDB (Linux), LLDB (macOS) или отладчик MSVC (Windows)
  • IDE с поддержкой Rust: VS Code с rust-analyzer, CLion или IntelliJ IDEA
  • Основная библиотека Plugify (собранная и доступная)
  • Установленный и настроенный языковой модуль Rust

Сборки Debug и Release

Сборка Debug

Сборки Debug содержат отладочную информацию и не оптимизированы:

cargo build

Особенности:

  • Полные отладочные символы
  • Без оптимизации
  • Более быстрая компиляция
  • Проще отлаживать
  • Больший размер бинарника
  • Более медленное выполнение

Сборка Release

Сборки Release оптимизированы, но их сложнее отлаживать:

cargo build --release

Особенности:

  • Оптимизированный код
  • Возможно встраивание функций
  • Сложнее пошагово проходить код
  • Меньший размер бинарника
  • Более быстрое выполнение

Release с отладочной информацией

Лучшее из обоих вариантов для отладки проблем в продакшене:

Cargo.toml
[profile.release]
debug = true
strip = false
cargo build --release

Инструменты отладки

1. Использование rust-gdb (Linux)

Сборка с отладочной информацией

cargo build

Подключение отладчика

rust-gdb target/debug/libplugin_name.so

# Или подключение к запущенному процессу
rust-gdb -p <plugify_pid>

Установка точек останова

(gdb) break plugin_name::on_plugin_start
(gdb) break src/lib.rs:42

Запуск и отладка

(gdb) run
(gdb) continue
(gdb) next
(gdb) step
(gdb) print variable_name
(gdb) backtrace

2. Использование rust-lldb (macOS/Linux)

Сборка с отладочной информацией

cargo build

Запуск отладчика

rust-lldb target/debug/libplugin_name.so

Основные команды

(lldb) breakpoint set --name on_plugin_start
(lldb) breakpoint set --file lib.rs --line 42
(lldb) run
(lldb) next
(lldb) step
(lldb) frame variable
(lldb) bt

3. Использование Visual Studio Code

Установка расширений

  • rust-analyzer: поддержка языка Rust
  • CodeLLDB: интеграция с отладчиком LLDB

Настройка launch.json

.vscode/launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "type": "lldb",
            "request": "launch",
            "name": "Debug Plugin",
            "cargo": {
                "args": [
                    "build",
                    "--lib"
                ]
            },
            "program": "${workspaceFolder}/target/debug/libplugin_name.so",
            "cwd": "${workspaceFolder}",
            "sourceLanguages": ["rust"]
        },
        {
            "type": "lldb",
            "request": "attach",
            "name": "Attach to Plugify",
            "program": "/path/to/plugify",
            "pid": "${command:pickProcess}"
        }
    ]
}

Установка точек останова

Щёлкните на левом поле рядом с номерами строк в ваших исходных файлах.

Запуск отладки

Нажмите F5 или выберите «Run and Debug» → «Debug Plugin»

4. Использование CLion/IntelliJ IDEA

Откройте проект

Откройте файл Cargo.toml как проект.

Настройте отладчик

  1. Перейдите в Run → Edit Configurations
  2. Добавьте Rust Cargo Command
  3. Укажите команду: build
  4. Задайте рабочий каталог — корень проекта

Установите точки останова

Щёлкните на поле рядом с номерами строк.

Запустите отладку

Нажмите на иконку отладки или Shift+F9.

Логирование и трассировка

Использование println! для базового логирования

fn on_plugin_start() {
    println!("Plugin starting...");
    println!("Debug: variable = {:?}", some_variable);
}

Использование макроса dbg!

fn process_data(value: i32) -> i32 {
    dbg!(value);  // Выводит: [src/lib.rs:42] value = 42
    let result = value * 2;
    dbg!(result)  // Возвращает result и одновременно выводит его
}

Использование крейта log

Cargo.toml
src/lib.rs
[dependencies]
plugify = { git = "https://github.com/untrustedmodders/rust-plugify" }
log = "0.4"
env_logger = "0.11"

Задайте уровень логирования через переменную окружения:

RUST_LOG=debug cargo run
RUST_LOG=plugin_name=trace cargo run

Использование крейта tracing

Для более продвинутого логирования и инструментирования:

Cargo.toml
src/lib.rs
[dependencies]
tracing = "0.1"
tracing-subscriber = "0.3"

Распространённые сценарии отладки

1. Падения плагина

Симптомы: плагин падает или вызывает segfault.

Шаги отладки:

# Запуск с трассировкой стека
RUST_BACKTRACE=1 cargo run

# Полная трассировка стека
RUST_BACKTRACE=full cargo run

# Использование отладчика
rust-gdb target/debug/libplugin_name.so

Проверьте:

  • Разыменование нулевых указателей
  • Выход за границы массива
  • Проблемы в unsafe-коде
  • Проблемы на границе FFI

2. Плагин не загружается

Симптомы: Plugify не загружает плагин.

Шаги отладки:

  1. Проверьте логи Plugify
  2. Проверьте файл манифеста (.pplugin)
  3. Убедитесь, что библиотека находится в правильном месте
  4. Проверьте зависимости библиотеки:
    # Linux
    ldd target/release/libplugin_name.so
    
    # macOS
    otool -L target/release/libplugin_name.dylib
    
    # Windows
    dumpbin /dependents target/release/plugin_name.dll
    

3. Проблемы с памятью

Симптомы: утечки или повреждение памяти.

Использование Valgrind (Linux):

valgrind --leak-check=full \
         --show-leak-kinds=all \
         --track-origins=yes \
         /path/to/plugify

Использование AddressSanitizer:

Cargo.toml
[profile.dev]
opt-level = 1

[profile.dev.package."*"]
opt-level = 3
RUSTFLAGS="-Z sanitizer=address" cargo build --target x86_64-unknown-linux-gnu

4. Проблемы с производительностью

Использование инструментов профилирования:

# Установка flamegraph
cargo install flamegraph

# Генерация flamegraph
cargo flamegraph

# Или использование perf (Linux)
cargo build --release
perf record --call-graph=dwarf /path/to/plugify
perf report

Техники отладки

1. Условная компиляция

#[cfg(debug_assertions)]
fn debug_info() {
    println!("Debug mode only");
}

fn on_plugin_start() {
    #[cfg(debug_assertions)]
    debug_info();

    #[cfg(not(debug_assertions))]
    println!("Release mode");
}

2. assert и debug_assert

fn process_value(value: i32) {
    assert!(value >= 0, "Value must be non-negative");

    // Только в отладочных сборках
    debug_assert!(value < 1000, "Value too large");
}

3. Пользовательский вывод Debug

#[derive(Debug)]
struct Config {
    name: String,
    value: i32,
}

let config = Config {
    name: "test".to_string(),
    value: 42,
};
println!("{:?}", config);      // Формат Debug
println!("{:#?}", config);     // Форматированный вывод Debug

4. Обработчики паник

use std::panic;

fn on_plugin_start() {
    panic::set_hook(Box::new(|panic_info| {
        eprintln!("Plugin panic: {:?}", panic_info);
        // Запись в файл, отправка в систему мониторинга и т.д.
    }));
}

Продвинутая отладка

1. Отладочные макросы

macro_rules! debug_println {
    ($($arg:tt)*) => {
        #[cfg(debug_assertions)]
        println!($($arg)*);
    };
}

debug_println!("Debug: value = {}", 42);

2. Отладка асинхронного кода

use tracing::instrument;

#[instrument]
async fn async_operation() {
    tracing::info!("Starting async operation");
    // Асинхронная работа здесь
}

3. Удалённая отладка

Для отладки на удалённых системах:

# На удалённой системе
gdbserver :1234 /path/to/plugify

# На локальной системе
rust-gdb
(gdb) target remote remote-host:1234

Устранение неполадок

Отладчик не останавливается на точках останова

Решения:

  • Убедитесь, что отладочные символы включены: debug = true в Cargo.toml
  • Пересоберите проект: cargo clean && cargo build
  • Проверьте, что точка останова находится в достижимом коде
  • Убедитесь, что отладчик подключён к правильному процессу

Не видно значений переменных

Решения:

  • В сборках release переменные могут быть удалены оптимизацией
  • Используйте debug = true в профиле release
  • Добавьте #[inline(never)], чтобы предотвратить встраивание
  • Проверьте, что переменная находится в области видимости

Символы не загружаются

Решения:

  • Установите скрипты отладчика Rust: rust-gdb, rust-lldb
  • Проверьте наличие отладочной информации: objdump -h target/debug/libplugin_name.so | grep debug
  • Убедитесь, что версии Rust у отладчика и в коде совпадают

Рекомендации

  1. Собирайте с отладочными символами во время разработки
  2. Используйте логирование вместо println! в продакшене
  3. Включайте все предупреждения компилятора: #![warn(clippy::all)]
  4. Используйте фреймворк тестирования Rust: cargo test
  5. Включайте трассировку стека при разработке: RUST_BACKTRACE=1
  6. Профилируйте перед оптимизацией: измеряйте, а не гадайте
  7. Используйте статический анализ: cargo clippy
  8. Проверяйте проблемы с памятью: используйте санитайзеры
  9. Документируйте шаги отладки: ведите документацию по устранению неполадок
  10. Тестируйте пути с ошибками: не ограничивайтесь только успешными сценариями

Полезные ресурсы

Дополнительную информацию об отладке приложений на Rust можно найти здесь:

Заключение

Эффективная отладка критически важна для разработки надёжных плагинов на Rust. Используя отличный инструментарий Rust, подробные сообщения об ошибках и гарантии безопасности, вы сможете быстро находить и устранять проблемы. Сочетание проверок Rust на этапе компиляции и инструментов отладки во время выполнения даёт мощную среду для создания надёжных плагинов Plugify.