ПрограммированиеBackend разработчик

Объясните, как работает система владения (ownership) в Rust и как она обеспечивает безопасность памяти без сборщика мусора?

Проходите собеседования с ИИ помощником Hintsage

Ответ

Система владения (ownership) — это основная концепция Rust для обеспечения безопасности памяти на уровне компиляции. У каждой переменной есть владелец. Только один владелец ресурса может существовать в определённый момент времени.

Владение передаётся (move) при присваивании или передаче в функцию. После передачи прежний владелец не может использовать значение:

let s = String::from("hello"); let t = s; // s больше недоступен

Rust также различает заимствование (ссылки).

  • &T — ссылка только для чтения (borrow).
  • &mut T — изменяемая ссылка (mutable borrow), но только одна может быть в одном времени жизни.

С помощью этих правил Rust гарантирует, что не возникнет гонок данных, используемых после освобождения памяти и других ошибок управления ресурсами.

Вопрос с подвохом

Может ли быть более одной изменяемой ссылки (&mut T) одновременно у одного значения? Почему?

Ответ: Нет, в каждый момент времени может быть либо любое количество неизменяемых ссылок, либо только одна изменяемая. Это предотвращает гонки данных. Пример неверного кода:

let mut s = String::from("hi"); let r1 = &mut s; let r2 = &mut s; // ошибка компиляции!

Примеры реальных ошибок из-за незнания тонкостей темы


История

В одном мультипоточном проекте разработчик пытался хранить ссылки на изменяемый буфер, не используя владение, что приводило к сбоям (use-after-free), когда буфер освобождался до завершения работы со ссылкой. Rust не позволил скомпилировать такой код, поэтому пришлось изменить архитектуру.


История

На старте большого проекта Rust программисты мигрировали код с C++. Они пытались совместить устаревшие привычки работы с "сырыми" указателями, что приводило к ошибкам с владением ресурсами и постоянным паникам borrow checker'а, пока не была решена архитектурная проблема владения.


История

В библиотеке парсинга строк ошибки с двойным освобождением памяти удалось избежать только благодаря строгой системе владения Rust. Аналогичная библиотека на C++ приводила к трудноловимым багам и утечкам памяти.