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

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

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

Ответ

В Rust есть два основных вида ссылок:

  • Немутируемые ссылки (&T): предоставляют доступ только для чтения.
  • Мутабельные ссылки (&mut T): позволяют изменять значение, на которое ссылаются.

Правила:

  • Одновременно может быть либо любое число немутируемых ссылок, либо только одна мутабельная; нельзя смешивать в одной области видимости.
  • Ссылки имеют свой срок жизни (lifetime), который анализируется на этапе компиляции.

Примеры синтаксиса:

fn read(val: &i32) { println!("{}", val); } fn write(val: &mut i32) { *val += 1; } let mut x = 5; read(&x); write(&mut x);

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

Вопрос: Можно ли создать две мутабельные ссылки на одну переменную в разных областях видимости одной функции?

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

let mut x = 10; let r1 = &mut x; { let r2 = &mut x; // ошибка! }

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


История

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


История

На старте проекта по обработке данных один из участников не делал "reanalyze borrow checker" для сложного кода с вложенными областями. В результате, из-за пересекающихся ссылок вылезла классическая "cannot borrow as mutable because it's also borrowed as immutable"-ошибка без явного указания в исходном коде места проблемы.


История

В мультитрединговом коде использовали обычные ссылки для доступа к разделяемым данным. При попытке изменить данные в параллельных потоках получали неожиданные ошибки компилятора и гонки данных при обходе borrow checker через небезопасный код.