Небезпечні функції
Виклик небезпечних функцій
Функцію або метод можна позначити як 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); }
Виклик небезпечних функцій
get_unchecked
, як і більшість функцій _unchecked
, небезпечна, оскільки може створити UB, якщо діапазон невірний. Функція abs
некоректна з іншої причини: вона є зовнішньою функцією (FFI). Виклик зовнішніх функцій зазвичай є проблемою лише тоді, коли ці функції роблять щось із вказівниками, що може порушити модель пам'яті Rust, але загалом будь-яка функція C може мати невизначену поведінку за довільних обставин.
У цьому прикладі "C"
- це ABI; інші ABI також доступні.
Написання небезпечних функцій
Насправді ми не будемо використовувати вказівники для функції swap
- це можна безпечно зробити за допомогою посилань.
Зверніть увагу, що небезпечний код дозволяється всередині небезпечної функції без блоку unsafe
. Ми можемо заборонити це за допомогою #[deny(unsafe_op_in_unsafe_fn)]
. Спробуйте додати його і подивіться, що станеться. Ймовірно, це буде змінено у майбутньому виданні Rust..