Unsafe Rust — это расширение безопасного подмножества Rust, позволяющее использовать операции, которые компилятор не может проверить на корректность владения, сроков жизни и алиасинга. Основные области применения: взаимодействие с низкоуровневыми библиотеками, FFI, ручной контроль памяти, реализация абстракций, не укладывающихся в модель безопасного Rust.
Ключевые особенности unsafe:
unsafe { ... } или функцию: unsafe fn some_func()Пример:
let x: i32 = 10; let ptr: *const i32 = &x as *const i32; unsafe { println!("Value: {}", *ptr); // разыменование raw pointer }
Является ли код внутри unsafe-блока полностью небезопасным и не чекан компилятором, или компилятор по-прежнему применяет правила borrow checker и другие проверки?
Ответ: Нет, внутри unsafe-блока компилятор продолжает проверять множество правил Rust (например, типизация, правила владения, синтаксис), но позволяет выполнять только те действия, которые иначе бы не допустил. Нельзя полностью отключить borrow checker!
Пример:
let mut x = 0; let r1 = &mut x as *mut i32; // Запрещено: let r2 = &mut x as *mut i32; // даже внутри unsafe появятся ошибки, если нарушается мутабельность
История
В асинхронной файловой библиотеке был использован raw pointer для контроля буфера, но забыли корректно отслеживать срок жизни буфера. В результате, при закрытии файла, pointer стал "висячим" и access приводил к undefined behavior (секция unsafe не спасла от use-after-free).
История
В собственной реализации Vec-like структуры программист вручную расширял буфер через unsafe. Ошибка смещения привела к некорректному копированию элементов и data corruption, потому что не были учтены alignment и layout типов.
История
В дескрипторе потоков использовался статический мутабельный указатель (static mut) без должной синхронизации. Из-за этого в многопоточном режиме случайно возникло data race, приводящее к sporadic crash приложения, отлавливаемому только fuzzing.