Небезопасный код¶
Ü по умолчанию не допускает ряд операций, считающимися небезопасными:
- явное обращение к конструкторам или деструкторам
- обращение к глобальным изменяемым переменным
- разыменование сырого указателя
- арифметические операции над сырыми указателями
- оператор
cast_ref_unsafe
- оператор
cast_mut
- инициализатор
ununitialized
- вызов
unsafe
функции
Если же какая-то из этих операций необходима, её следует обернуть в unsafe
блок.
Данный блок состоит из ключевого слова unsafe
и бока после него.
В даном блоке разрешены все unsafe
операции.
fn Foo()
{
unsafe
{
var i32 mut x= uninitialized;
x= 42;
}
}
Внутри unsafe
блока также можно объявить safe
блок, чтобы на время запретить небезопасные операции.
fn Bar() unsafe;
fn Foo()
{
unsafe
{
Bar(); // Ок, можно звать "unsafe" функцию
safe
{
Bar(); // Ошибка, здесь звать "unsafe" нельзя
}
Bar(); // Ок, теперь снова можно
}
}
Кроме unsafe
блоков существуют также unsafe
выражения.
По поведению они схожи с unsafe
блоками, но действуют на уровне выражений.
Аналогично с safe
блоками существует и safe
выражения.
fn Bar() unsafe : i32;
fn Foo()
{
var i32 x= 2 * unsafe(Bar()); // Ок - unsafe контекст распространяется только на вызов unsafe функции.
}
Небезопасные функции¶
Небезопасные функции - функции, которые просто так звать не безопасно и перед вызовом которых обычно требуется соблюсти ряд условий.
Небезопасные функции помечаются ключевым словом unsafe
после списка аргументов функции и списка связывания ссылок.
Такие функции можно звать только внутри unsafe
блока.
Тело unsafe
функции не является unsafe
блоком, если внутри неё нужно выполнить небезопасные операции, их нужно обернуть в unsafe
блок.
fn Bar( i32 d ) unsafe : i32
{
unsafe
{
var i32 mut x= uninitialized;
x= 100 / d;
return x;
}
}
fn Foo()
{
unsafe
{
Bar( 7 );
}
}