2025-11-17 10:43:18 +07:00

8.1 KiB
Raw Blame History

  • Умеет писать unsafe код и безопасные обёртки для него.

  • Понимает причины UB и знает, как его не допустить. (откуда взялось, что значит и как может нанести вред работе программы)

  • для автора - проверка ОРа квизами, включая примеры кода.

  • Умеет проектировать безопасный интерфейс для unsafe кода.

  • Знает best practice для написания unsafe кода.

  • Можно использовать примеры из third party крейтов.

  • Начать с проблемы, когда компилятор не может гарантировать безопасность по памяти (но без этого невозможно написать программу), возможно из ub

  • Рассказать про причины ub

  • Рассказать, чем является unsafe, ответственность на программисте, про ub (НЕ является избавлением от borrow checker)

  • Рассказать про применение unsafe (взаимодействие с С, оптимизация (вспомнить небезопасную либу для бэкенда: rocket или actix), написание основы/базы языка)

  • Определении функции unsafe если соблюдение инвариантов висит на пользователе (при написании такой функции смотреть - является ли сам интерфейс функции safe)

  • примеры из third party

  • Рассказать про бест практис при написании unsafe:

    • Лучший unsafe - отсутствующий unsafe
    • Уменьшение зоны unsafe (легче найти баг + проще просчитать ub)
    • Safety
    • SAFETY
    • assert_unsafe_precondition!
    • ...
  • Практика

  • Лайфтаймы как помошники при взаимодействии с c abi

  • Drop

Почему unsafe внутри unsafe fn: фн показывает, что инварианты должен соблюдать пользователь функции ансейф блок же показывает скоуп, где нужно искать баги (где они и будут тк анйсейф операция) подводный камень: при ансейф баг может возникать в любом из блоков анйсефа, даже если он возникает в другом месте

ub: из-за различий архитектру цп и ос и для оптимизаций

еслм возникает баг, значит неправильно реализованы инварианты в одном из unsafe блоков с которым взаимодействовали (даже в совершенно другом месте)

Возможно рассказать еще про это все?

  • pointers
  • nonnull
  • phantomdata (инвариантность/ковариантность и тд)
  • unsafecell
  • send/sync + unsafe trait markers (мб практический пример: написание собстенного mutex)
  • unsafe traits

При описании бест практис про Safety, привести пример, почему нужно (а еще потому, что при изменении логики функции самим тоже нужно следить, какие инварианты висят за пользователем) Практика: подумайте над тем, какие инварианты тут должны быть соблюдены и какие из них не соблюдены. или пропробовать найти несоблюденный инвариант и "взломать" программу?) допустим, нам нужно дя создания сокета узнать, можем ли мы использовать tcp/udp/icmp/etc, для этого используем сискол WSAEnumProtocolsA

Start

В прошлом уроке мы научились использовать C функции в своем rust коде. Давайте же расширим свои знания, и научимся взаимодействовать с таким кодом. В прошлом уроке в практическом задании вам встречался такой код:

include!(concat!(env!("OUT_DIR"), "/bindgen.rs"));

use std::ffi::{CStr, CString};

const TEST_JSON: &CStr = c"{
    \"meaning_of_life\": 42
}";

fn main() {
    let json: *mut cJSON = unsafe { cJSON_Parse(TEST_JSON.as_ptr()) };

    let json_str = unsafe { cJSON_PrintUnformatted(json) };
    let json_str = unsafe { CString::from_raw(json_str) };
    let json_str = json_str.to_str().unwrap();
    assert_eq!(json_str, r#"{"meaning_of_life":42}"#);

    let meaning_of_life = unsafe { cJSON_GetObjectItem(json, c"meaning_of_life".as_ptr()) };
    let meaning_of_life = unsafe { cJSON_GetNumberValue(meaning_of_life) };
    println!("Meaning of life: {}", meaning_of_life);
    assert_eq!(meaning_of_life, 42f64);
}

У json обозначен не встречавшийся до этого тип *mut _

Указатели

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

Начать с проблемы, когда компилятор не может гарантировать безопасность по памяти (но без этого невозможно написать программу), возможно из ub Допустим, на вход вашей функции

Рассказать про причины ub

  • как в математике есть неопределенности (к примеру, для деления на ноль), так и в языках программирования тоже есть свои неопределенности. Именно для этого и было создана такая вещь, как неопределённое поведение.

Рассказать, чем является unsafe, ответственность на программисте, про ub (НЕ является избавлением от borrow checker)

Рассказать про применение unsafe (взаимодействие с С, оптимизация (вспомнить небезопасную либу для бэкенда: rocket или actix), написание основы/базы языка)

Практика по пути

  • Определении функции unsafe если соблюдение инвариантов висит на пользователе (при написании такой функции смотреть - является ли сам интерфейс функции safe)
  • примеры из third party
  • Рассказать про бест практис при написании unsafe:
    • Лучший unsafe - отсутствующий unsafe
    • Уменьшение зоны unsafe (легче найти баг + проще просчитать ub)
    • Safety
    • SAFETY
    • assert_unsafe_precondition!
    • ...
  • Практика
  • Лайфтаймы как помошники при взаимодействии с c abi
  • Drop