Паника
Паника — это основная часть языка Rust. Встроенные операции, такие как индексация, проверяются во время выполнения на предмет безопасности памяти. При попытке индексации за пределами границ массива возникает паника.
В стандартной библиотеке поведение паники определено: оно разворачивает стек вызывающего потока, если пользователь не выбрал завершение программы при панике.
Однако в программах без стандартной библиотеки поведение паники остается неопределенным. Поведение можно выбрать, объявив функцию #[panic_handler]. Эта функция должна появляться ровно один раз в графе зависимостей программы и иметь следующую сигнатуру: fn(&PanicInfo) -> !, где PanicInfo — это структура, содержащая информацию о месте возникновения паники.
Учитывая, что встраиваемые системы варьируются от пользовательских до критически важных для безопасности (не могут завершаться сбоем), не существует универсального поведения при панике, но есть множество часто используемых поведений. Эти общие поведения были упакованы в крейты, которые определяют функцию #[panic_handler]. Некоторые примеры включают:
panic-abort. Паника вызывает выполнение инструкции прерывания.panic-halt. Паника приводит к остановке программы или текущего потока в бесконечном цикле.panic-itm. Сообщение о панике записывается с использованием ITM, периферийного устройства, специфичного для ARM Cortex-M.panic-semihosting. Сообщение о панике отправляется на хост с использованием техники семихостинга.
Вы можете найти еще больше крейтов, выполнив поиск по ключевому слову panic-handler на crates.io.
Программа может выбрать одно из этих поведений, просто подключив соответствующий крейт...
#![no_main]
#![no_std]
// Профиль dev: упрощает отладку паник; можно установить точку останова на `rust_begin_unwind`
#[cfg(debug_assertions)]
use panic_halt as _;
// Профиль release: минимизирует размер бинарного файла приложения
#[cfg(not(debug_assertions))]
use panic_abort as _;
// ..
В этом примере крейт подключается к panic-halt при сборке с профилем dev (cargo build), но к panic-abort при сборке с профилем release (cargo build --release).
Форма инструкции
use panic_abort as _;используется для обеспечения включения обработчика паникиpanic_abortв итоговый исполняемый файл, при этом ясно указывая компилятору, что мы не будем явно использовать что-либо из крейта. Без переименованияas _компилятор выдал бы предупреждение о неиспользуемом импорте. Иногда можно встретитьextern crate panic_abortвместо этого, что является старым стилем, использовавшимся до издания Rust 2018, и теперь должно использоваться только для "sysroot" крейтов (распространяемых вместе с Rust), таких какproc_macro,alloc,stdиtest.
Пример
Вот пример, который пытается индексировать массив за его пределами. Эта операция приводит к панике.
#![no_main]
#![no_std]
use panic_semihosting as _;
use cortex_m_rt::entry;
#[entry]
fn main() -> ! {
let xs = [0, 1, 2];
let i = xs.len();
let _y = xs[i]; // Доступ за пределами массива
loop {}
}
В этом примере выбрано поведение panic-semihosting, которое выводит сообщение о панике на консоль хоста с использованием семихостинга.
$ cargo run
Running `qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb (..)
panicked at 'index out of bounds: the len is 3 but the index is 4', src/main.rs:12:13
Вы можете попробовать изменить поведение на panic-halt и убедиться, что в этом случае сообщение не выводится.