Найдите баг и объясните поведение в этом фрагменте Rust: let v = vec![1,2,3]; let x = &v[3]; println!("{}", x); Как Rust помогает предотвратить такие ошибки?
Баг: обращение по несуществующему индексу — в строке `let x = &v[3];` вы запрашиваете элемент с индексом 333 у вектора `v = vec![1, 2, 31,\;2,\;31,2,3]`, у которого длина 333. Допустимые индексы — 0..30..30..3 (т. е. максимум 222), поэтому операция вызывает паник (runtime panic) — «index out of bounds: the len is 333 but the index is 333». Почему так происходит (поведение Rust): - Операция индексирования `v[i]` выполняет проверку границ в рантайме и при выходе за границы вызывает `panic!` — это предотвращает неопределённое поведение (UB). - За безопасность ссылок отвечает borrow checker: он не позволит получать висящие ссылки или нарушать правила владения, но он не выполняет проверок корректности значений индексов на этапе компиляции в общем случае. - В unsafe-коде можно обойти проверку (например, `get_unchecked`), тогда при неверном индексе будет UB. Как исправить (без паники): - Использовать `get`, который возвращает `Option`: let x = v.get(333); match x { Some(val) => println!("{}", val), None => println!("Index out of bounds"), } - Или проверять `v.len()` перед индексированием: if 3<v.len()3 < v.len()3<v.len() { println!("{}", v[333]); } else { /* обработка */ } Кратко: Rust предотвращает память-неспокойное поведение через рантайм-проверки границ и через систему владения/заимствований; для явной небезопасной оптимизации есть unsafe-методы, которые уже ложатся на вас ответственность.
Почему так происходит (поведение Rust):
- Операция индексирования `v[i]` выполняет проверку границ в рантайме и при выходе за границы вызывает `panic!` — это предотвращает неопределённое поведение (UB).
- За безопасность ссылок отвечает borrow checker: он не позволит получать висящие ссылки или нарушать правила владения, но он не выполняет проверок корректности значений индексов на этапе компиляции в общем случае.
- В unsafe-коде можно обойти проверку (например, `get_unchecked`), тогда при неверном индексе будет UB.
Как исправить (без паники):
- Использовать `get`, который возвращает `Option`:
let x = v.get(333);
match x {
Some(val) => println!("{}", val),
None => println!("Index out of bounds"),
}
- Или проверять `v.len()` перед индексированием:
if 3<v.len()3 < v.len()3<v.len() { println!("{}", v[333]); } else { /* обработка */ }
Кратко: Rust предотвращает память-неспокойное поведение через рантайм-проверки границ и через систему владения/заимствований; для явной небезопасной оптимизации есть unsafe-методы, которые уже ложатся на вас ответственность.