原始指针的数据消失
Raw pointer's data disappearing
考虑以下代码:
struct Person {
mate: Option<*const Person>,
siblings: Vec<i32>,
}
impl Person {
fn meets(&mut self, mate: &mut Person) {
self.mate = Some(mate);
mate.mate = Some(self);
}
}
struct Bar {
person: Person,
}
impl Bar {
fn addr(&self) {
unsafe {
println!("\n`bob.siblings.len()`: {}, `bob.susan.siblings.len()`: {}",
self.person.siblings.len(), (*self.person.mate.unwrap()).siblings.len());
println!("\n but wait -> `bob.susan.bob.siblings.len()`: {} ??",
(*(*self.person.mate.unwrap()).mate.unwrap()).siblings.len());
println!("\nthis is `bob.susan.bob's address`: {:p} => same address inside bar ???",
(*self.person.mate.unwrap()).mate.unwrap());
}
}
}
fn main() {
let mut bob = Person {
mate: None,
siblings: {
let mut stuff: Vec<i32> = Vec::new();
unsafe {
stuff.set_len(2);
}
stuff
}
};
let mut susan = Person {
mate: None,
siblings: {
let mut stuff: Vec<i32> = Vec::new();
unsafe {
stuff.set_len(4);
}
stuff
}
};
bob.meets(&mut susan);
println!("\nbob has {} `siblings` before entering the `bar`.", bob.siblings.len());
println!("\nthis is bob's address: {:p}", &bob);
let bar = Bar { person: bob };
bar.addr();
}
结果:
bob has 2 `siblings` before entering the `bar`.
this is bob's address: 0x7fff556ab470
`bob.siblings.len()`: 2, `bob.susan.siblings.len()`: 4
but wait -> `bob.susan.bob.siblings.len()`: 0 ??
this is `bob.susan.bob's address`: 0x7fff556ab470 => same address inside bar ???
我的问题是,bob.siblings
去哪儿了?即使我通过 susan
调用 bob.siblings
(bob.mate.mate.siblings
-> bob.susan.bob.siblings
),结果不应该是一样的吗?
如何调用 bob.susan.bob.siblings
并获得与调用 bob.siblings
相同的结果?
Rust 版本:rustc 1.0.0-nightly (270a677d4 2015-03-07) (built 2015-03-07)
这将是 Rust 帮助防止的一个很好的例子,但你故意关闭了安全检查,现在我们回到 C。检查这一行:
let bar = Bar { person: bob };
这一行将存储在bob
中的数据移动到bar
中。这意味着指针已 无效 并且您不能信任任何值。让我们稍后添加:
println!("\nthis is bob's address: {:p}", &bob);
let bar = Bar { person: bob };
println!("\nthis is the bar's address: {:p}", &bar);
println!("\nthis is bob's new address: {:p}", &bar.person);
// this is bob's address: 0x7fffe10518c0
// this is the bar's address: 0x7fffe10517d0
// this is bob's new address: 0x7fffe10517d0
当你试图争论哪些指针正确哪些不正确时,你现在正处于一个受伤的世界中!
解决这个问题的一种方法是不动bob
。取而代之的是参考:
struct Bar<'a> {
person: &'a Person,
}
// ...
let bar = Bar { person: &bob };
另一种方法是在 移动到 bar
:
之后调用 meets
let mut bar = Bar { person: bob };
bar.person.meets(&mut susan);
另一种方法是 Box
(或使用 Arena
)数据。然后数据没有在堆栈上分配,因此值的地址在移动时不会改变:
struct Bar {
person: Box<Person>,
}
// ...
let mut bob = Box::new(Person { });
let mut susan = Box::new(Person { });
考虑以下代码:
struct Person {
mate: Option<*const Person>,
siblings: Vec<i32>,
}
impl Person {
fn meets(&mut self, mate: &mut Person) {
self.mate = Some(mate);
mate.mate = Some(self);
}
}
struct Bar {
person: Person,
}
impl Bar {
fn addr(&self) {
unsafe {
println!("\n`bob.siblings.len()`: {}, `bob.susan.siblings.len()`: {}",
self.person.siblings.len(), (*self.person.mate.unwrap()).siblings.len());
println!("\n but wait -> `bob.susan.bob.siblings.len()`: {} ??",
(*(*self.person.mate.unwrap()).mate.unwrap()).siblings.len());
println!("\nthis is `bob.susan.bob's address`: {:p} => same address inside bar ???",
(*self.person.mate.unwrap()).mate.unwrap());
}
}
}
fn main() {
let mut bob = Person {
mate: None,
siblings: {
let mut stuff: Vec<i32> = Vec::new();
unsafe {
stuff.set_len(2);
}
stuff
}
};
let mut susan = Person {
mate: None,
siblings: {
let mut stuff: Vec<i32> = Vec::new();
unsafe {
stuff.set_len(4);
}
stuff
}
};
bob.meets(&mut susan);
println!("\nbob has {} `siblings` before entering the `bar`.", bob.siblings.len());
println!("\nthis is bob's address: {:p}", &bob);
let bar = Bar { person: bob };
bar.addr();
}
结果:
bob has 2 `siblings` before entering the `bar`.
this is bob's address: 0x7fff556ab470
`bob.siblings.len()`: 2, `bob.susan.siblings.len()`: 4
but wait -> `bob.susan.bob.siblings.len()`: 0 ??
this is `bob.susan.bob's address`: 0x7fff556ab470 => same address inside bar ???
我的问题是,bob.siblings
去哪儿了?即使我通过 susan
调用 bob.siblings
(bob.mate.mate.siblings
-> bob.susan.bob.siblings
),结果不应该是一样的吗?
如何调用 bob.susan.bob.siblings
并获得与调用 bob.siblings
相同的结果?
Rust 版本:rustc 1.0.0-nightly (270a677d4 2015-03-07) (built 2015-03-07)
这将是 Rust 帮助防止的一个很好的例子,但你故意关闭了安全检查,现在我们回到 C。检查这一行:
let bar = Bar { person: bob };
这一行将存储在bob
中的数据移动到bar
中。这意味着指针已 无效 并且您不能信任任何值。让我们稍后添加:
println!("\nthis is bob's address: {:p}", &bob);
let bar = Bar { person: bob };
println!("\nthis is the bar's address: {:p}", &bar);
println!("\nthis is bob's new address: {:p}", &bar.person);
// this is bob's address: 0x7fffe10518c0
// this is the bar's address: 0x7fffe10517d0
// this is bob's new address: 0x7fffe10517d0
当你试图争论哪些指针正确哪些不正确时,你现在正处于一个受伤的世界中!
解决这个问题的一种方法是不动bob
。取而代之的是参考:
struct Bar<'a> {
person: &'a Person,
}
// ...
let bar = Bar { person: &bob };
另一种方法是在 移动到 bar
:
meets
let mut bar = Bar { person: bob };
bar.person.meets(&mut susan);
另一种方法是 Box
(或使用 Arena
)数据。然后数据没有在堆栈上分配,因此值的地址在移动时不会改变:
struct Bar {
person: Box<Person>,
}
// ...
let mut bob = Box::new(Person { });
let mut susan = Box::new(Person { });