Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Небезпечні функції

Виклик небезпечних функцій

Функцію або метод можна позначити як unsafe, якщо вони мають додаткові передумови, які ви повинні підтримувати, щоб уникнути невизначеної поведінки:

extern "C" {
    fn abs(input: i32) -> i32;
}

fn main() {
    let emojis = "🗻∈🌏";

    // БЕЗПЕКА: Індекси розташовані в правильному порядку в межах 
    // фрагмента рядка та лежать на межах послідовності UTF-8.
    unsafe {
        println!("смайлик: {}", emojis.get_unchecked(0..4));
        println!("смайлик: {}", emojis.get_unchecked(4..7));
        println!("смайлик: {}", emojis.get_unchecked(7..11));
    }

    println!("кількість символів: {}", count_chars(unsafe { emojis.get_unchecked(0..7) }));

    // БЕЗПЕКА: `abs` не працює з покажчиками і не має жодних вимог до
    // безпеки.
    unsafe {
        println!("Абсолютне значення -3 згідно з C: {}", abs(-3));
    }

    // Недотримання вимог кодування UTF-8 порушує безпеку пам’яті!
    // println!("смайлик: {}", unsafe { emojis.get_unchecked(0..3) });
    // println!("кількість символів: {}", count_chars(unsafe {
    // emojis.get_unchecked(0..3) }));
}

fn count_chars(s: &str) -> usize {
    s.chars().count()
}

Написання небезпечних функцій

Ви можете позначити власні функції як unsafe, якщо вони вимагають певних умов, щоб уникнути невизначеної поведінки.

/// Міняє місцями значення, на які вказують задані покажчики.
///
/// # Безпека
///
/// Покажчики повинні бути дійсними і правильно вирівняними.
unsafe fn swap(a: *mut u8, b: *mut u8) {
    let temp = *a;
    *a = *b;
    *b = temp;
}

fn main() {
    let mut a = 42;
    let mut b = 66;

    // БЕЗПЕКА: ...
    unsafe {
        swap(&mut a, &mut b);
    }

    println!("a = {}, b = {}", a, b);
}
This slide should take about 5 minutes.

Виклик небезпечних функцій

get_unchecked, як і більшість функцій _unchecked, небезпечна, оскільки може створити UB, якщо діапазон невірний. Функція abs небезпечна з іншої причини: вона є зовнішньою функцією (FFI). Виклик зовнішніх функцій зазвичай є проблемою лише тоді, коли ці функції роблять щось із вказівниками, що може порушити модель пам’яті Rust, але загалом будь-яка функція C може мати невизначену поведінку за довільних обставин.

У цьому прикладі "C" - це ABI; інші ABI також доступні.

Написання небезпечних функцій

Насправді ми не будемо використовувати вказівники для функції swap - це можна безпечно зробити за допомогою посилань.

Зверніть увагу, що небезпечний код дозволяється всередині небезпечної функції без блоку unsafe. Ми можемо заборонити це за допомогою #[deny(unsafe_op_in_unsafe_fn)]. Спробуйте додати його і подивіться, що станеться. Ймовірно, це буде змінено у майбутньому виданні Rust..