Однозначно не рекомендую его использовать, вы должны знать о том, как он работает, когда его можно использовать в качестве `rust` программатора.

Ключевое слово unsafe в Rust позволяет программистам перейти к низкоуровневому программированию с использованием указателей и многого другого. Однако небезопасный код должен подчиняться дополнительным правилам для соблюдения гарантий безопасности Rust. В этой статье рассматривается работа с небезопасным Rust с помощью небезопасных блоков, небезопасных функций, небезопасных свойств, рекомендаций, примеров и тематических исследований.

Небезопасные блоки

Небезопасные блоки — это части кода, отмеченные знаком unsafe { ... }. Операции внутри небезопасных блоков включают в себя:

Необработанные указатели

Необработанные указатели можно определять и использовать внутри небезопасных блоков. Например:

unsafe {
    let raw_ptr = 0x012345 as *mut u8;
}

Разыменование необработанных указателей

Необработанные указатели необходимо разыменовать для чтения или записи данных, на которые они указывают. Это небезопасно и может быть сделано только внутри небезопасных блоков:

unsafe {
    let raw_ptr = 0x012345 as *mut u8;
    *raw_ptr = 5; // Dereference raw pointer 
}

Вызов внешних функций

Функции из внешних библиотек (с использованием FFI) можно вызывать только внутри небезопасных блоков в Rust. Например, вызов функции printf() языка C:

unsafe {
    extern "C" {
        fn printf(s: *const u8, ...);
    }
    printf(b"Hello, world!\n");
}

Доступ или изменение статических переменных mut

Статические переменные в Rust по умолчанию неизменяемы и отмечены знаком static. Изменяемые статические переменные, отмеченные static mut, доступны или изменены только внутри небезопасных блоков:

static mut HELLO: u8 = 5;

unsafe {
    HELLO = 10;
}

Небезопасные функции

Небезопасные функции — это функции, отмеченные знаком unsafe fn. Они позволяют:

Работа с необработанными указателями в качестве аргументов функции

Необработанные указатели могут приниматься в качестве аргументов и возвращаться как результаты небезопасных функций. Например:

unsafe fn add_one(num: *mut u32) {
    *num += 1; 
}

Вызов внешних функций внутри функции

Как и небезопасные блоки, небезопасные функции могут вызывать внешние функции через FFI.

Доступ или изменение статических переменных mut

Небезопасные функции могут получать доступ к изменяемым статическим переменным и изменять их.

Небезопасные черты

Некоторые черты стандартной библиотеки, такие как Send и Sync, являются небезопасными. Типы, реализующие эти черты, обещают определенное поведение, поэтому их реализация, когда эти гарантии не могут быть соблюдены, является неопределенным поведением. Следовательно, они могут быть реализованы только для типов, использующих unsafe impl:

unsafe impl Send for MyType { ... }

Рекомендации по небезопасному коду

Некоторые ключевые рекомендации по работе с небезопасным Rust:

A. Сведите к минимуму использование небезопасного кода B. Убедитесь, что небезопасность оправдана C. Убедитесь, что небезопасные блоки минимальны D. Убедитесь, что необработанные указатели всегда действительны E. Отсутствие неопределенного поведения F. Правильное использование небезопасных функций и свойств

Примеры

Вот несколько примеров небезопасного кода Rust:

Разыменование необработанного указателя

unsafe {
    let raw_ptr = 0x012345 as *mut u8;
    *raw_ptr = 5; 
}

Вызов внешней функции C

unsafe {
    extern "C" {
        fn puts(s: *const u8);
    }
    puts(b"Hello\n");
}

Реализация признака Send для непотокобезопасного типа

use std::marker;

struct Foo {
    x: i32,
}

unsafe impl marker::Send for Foo {}

Доступ к статической переменной mut

static mut FOO: i32 = 0;

unsafe {
    FOO = 5;
    let a = FOO;
    println!("{}", a);
}

Когда следует избегать небезопасных

Лучше всего избегать небезопасного Rust, когда:

A. Существуют безопасные альтернативы B. Неуверенность в безопасности памяти C. Функциональность может быть достигнута без unsafe
D. Отладка и тестирование затруднены E. Небезопасный код можно изолировать и абстрагировать

Гарантии безопасности Rust гарантируют, что большинство программ можно написать без небезопасного кода. Выбирайте небезопасный режим только в случае крайней необходимости и с особой осторожностью.

Тематические исследования

Вот пара примеров небезопасного кода в известных проектах Rust:

Вектор

Vec<T> в Rust использует unsafe внутри, чтобы обеспечить прирост производительности за счет манипулирования указателями. Этот небезопасный код тщательно абстрагируется и предоставляются «безопасные» API.

Нелексическое время жизни

Функция нелексического времени жизни в Rust использует небезопасный код для реализации своей логики. Небезопасные блоки сведены к минимуму и хорошо протестированы.

кратер

Проект Crater, тестирующий нестабильные функции Rust, использует FFI для вызова библиотек C. Небезопасные блоки имеют модульную структуру и тщательно изучаются.

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