Вызов небезопасных функций
Несоблюдение требований безопасности нарушает безопасность памяти!
// Copyright 2025 Google LLC
// SPDX-License-Identifier: Apache-2.0
#[derive(Debug)]
#[repr(C)]
struct KeyPair {
pk: [u16; 4], // 8 байт
sk: [u16; 4], // 8 байт
}
const PK_BYTE_LEN: usize = 8;
fn log_public_key(pk_ptr: *const u16) {
let pk: &[u16] = unsafe { std::slice::from_raw_parts(pk_ptr, PK_BYTE_LEN) };
println!("{pk:?}");
}
fn main() {
let key_pair = KeyPair { pk: [1, 2, 3, 4], sk: [0, 0, 42, 0] };
log_public_key(key_pair.pk.as_ptr());
}
Всегда добавляйте комментарий о безопасности (// SAFETY:) к каждому блоку unsafe. Он должен объяснять, почему код действительно безопасен. В этом примере комментарий о безопасности отсутствует, и код некорректен.
Ключевые моменты:
- Второй аргумент
slice::from_raw_parts— это количество элементов, а не байтов! В этом примере демонстрируется неожиданное поведение: чтение за пределами одного массива и попадание в другой. - Это неопределённое поведение, потому что мы читаем за пределами массива, из которого был получен указатель.
log_public_keyдолжна бытьunsafe, потому чтоpk_ptrдолжен удовлетворять определённым предусловиям, чтобы избежать неопределённого поведения. Безопасную функцию, которая может вызвать неопределённое поведение, называютunsound(некорректной). Что должна говорить её документация о безопасности?- В стандартной библиотеке есть ряд низкоуровневых небезопасных функций. По возможности предпочитайте безопасные альтернативы!
- Если вы используете небезопасную функцию как оптимизацию, обязательно добавьте бенчмарк, чтобы продемонстрировать выигрыш.