原始指针的数据消失了

时间:2015-03-10 23:59:39

标签: rust

请考虑以下代码:

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去了哪里?即使我通过bob.siblingssusan - &gt; 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)

1 个答案:

答案 0 :(得分:17)

这将是Rust帮助预防的一个很好的例子,但是你故意关闭了安全检查,现在我们又回到C.检查这一行:

let bar = Bar { person: bob };

此行将<{1}}中存储的数据移动到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 }; 后调用meets

bar

另一个是let mut bar = Bar { person: bob }; bar.person.meets(&mut susan); (或使用Box)数据。然后数据不会在堆栈上分配,因此值的地址在移动时不会改变:

Arena