У меня есть что-то вроде следующего кода Rust, который может хранить объект Rust где-то (в реальном приложении он хранится в пользовательских данных Lua) и извлекать его позже (при вызове методов из Lua).Почему небезопасный код компилируется, но аналогичный код, который толкает вектор, жалуется, что ссылка не достаточно долгое время?
use std::ptr;
struct Bar(u32);
struct Foo<'a> {
subobj: &'a Bar,
}
struct State {
buf: [u8;100],
}
fn stash<T>(state: &mut State, foo: T) {
let p : *mut T = state.buf.as_ptr() as *mut T;
unsafe { ptr::write(p, foo); };
}
fn fetch<T>(state: &mut State) -> &mut T {
let p : *mut T = state.buf.as_ptr() as *mut T;
unsafe { &mut *p }
}
fn main() {
let mut state = State{buf: [0;100]};
// let mut v: Vec<Foo> = Vec::new();
{
let bar = Bar(7);
let foo = Foo { subobj: &bar };
// v.push(foo); // *does* complain that bar doesn't live long enough
stash(&mut state, foo);
} // bar's lifetime ends here!
let foo2: &mut Foo = fetch(&mut state); // Boom!
println!("{}", foo2.subobj.0 + 3);
}
В приведенном выше примере, очевидно, неправильно, так как это позволяет мне получить ссылку повисшего на bar
после его сфера закончилась. Однако казалось бы, что любой тип, не содержащий ссылок (или только 'static
), или что-то вроде Rc<T>
.
Почему эта компиляция, но очень похожая программа (нажимать на вектор вместо этого), жалуется (по желанию), что ссылка на bar
не проживает достаточно долго? Я не совсем понимаю, что отличает Vec::push
.
Мое понимание заключается в том, что typechecking рассматривает только функции, а не функции. Для этих целей код unsafe
не должен иметь значения; Дело в том, что я пытаюсь понять, как обернуть код unsafe
в безопасный интерфейс.
Это компилируется, потому что в небезопасном коде программист должен убедиться, что разыменование указателя действительно безопасно. –
100% согласны с A.B. Вот. Блок 'unsafe' сообщает компилятору:« Я буду защищать все гарантии безопасности памяти, потому что компилятор не может проверить их для меня », а затем вы идете и нарушаете все гарантии безопасности памяти. – Shepmaster
Но код «небезопасный» скрыт внутри функций - у меня создалось впечатление, что проверка типа остановлена у прототипа, а не заглядывает внутрь - и 'Vec' наверняка тоже небезопасный код под капотом. –