Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/mercurial/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Rust 为什么滴胶有时不流动?_Rust - Fatal编程技术网

Rust 为什么滴胶有时不流动?

Rust 为什么滴胶有时不流动?,rust,Rust,我在其他情况下也遇到过这种情况,但不会重复 基本上,有时候当你有一个*mut Foo,你用ptr::read()把它变成Foo时,有时候你的滴胶好像不起作用 下面是一个在playpen上运行而不使用FFI的可重复示例(这是将原始指针提升回对象的主要原因): i、 e.虽然我正在将闭包中的引用*mut Foo转换为T,但地精,龙,蝙蝠的滴胶不会运行 例如,如果稍微调整代码,可以运行这些(或其中一些): 向量存在时不删除内容 正在删除实例:1 丢了一根球棒 删除实例:2尝试使用不同的优化级别编译程序

我在其他情况下也遇到过这种情况,但不会重复

基本上,有时候当你有一个
*mut Foo
,你用
ptr::read()
把它变成
Foo
时,有时候你的滴胶好像不起作用

下面是一个在playpen上运行而不使用FFI的可重复示例(这是将原始指针提升回对象的主要原因):

i、 e.虽然我正在将闭包中的引用
*mut Foo
转换为
T
,但
地精
蝙蝠
的滴胶不会运行

例如,如果稍微调整代码,可以运行这些(或其中一些):

向量存在时不删除内容
正在删除实例:1
丢了一根球棒

删除实例:2尝试使用不同的优化级别编译程序。(Rust playpen上有一个用于此的下拉列表;默认值为
-O2
)您将看到输出不一致。在本例中,您正在调用未定义的行为

将项目添加到
Vec
时,您将创建包含
Foo
Bat
等对象,然后只在
Vec
中添加
Foo
Bat
不再存在。
IsFoo::as_foo
按值获取Bat,这意味着它获取了它的所有权。
Bat
作为_foo有效地放置在
的末尾,但是您通过调用
forget
抑制了放置胶

在“dispose”lambda中,通过将指向
Foo
的指针转换为指向
Bat
的指针,尝试获取
Bat
。这是未定义的行为,因为向量只包含
Foo
,而不是整个
Bat
。请记住,
Bat
在离开
IsFoo::as_foo
时被销毁


有了
-O2
-O3
,程序可能根本就没有创建
Vec
,而
Bat
Dragon
Goblin
值在堆栈上仍然完好无损。但是,
Goblin
没有
#[repr(C)]
,而另外两个有,所以这可能就是为什么析构函数没有只在那一个上运行。
在Rust 1.0
Drop
中,
#[repr(C)]
类型上不支持

这是因为
Drop
向结构中添加了一个隐藏标志,并且仅当该标志被设置时才运行析构函数

这是语言中一个已知的缺点,将来可能会通过跟踪带外的drop标志来改变它


有一个
#[safe_no_drop_flag]
可以删除
drop
标志,但是Rust不能保证析构函数被调用多少次(你的析构函数必须能够在已经被销毁的对象上安全运行)。

这个标题。。。是interestn@Coffee ? 滴胶就是它的名字,不是吗?当drop运行时……在这种情况下,我认为我们可以将drop实现称为“析构函数”,“drop glue”通常指自动生成的编译器内部,它们可以管理适当地调用用户定义的析构函数。将其移动到as_foo中会将其移动到as_foo的堆栈上,并移出main的堆栈,而main的堆栈在as_foo的末尾丢失。解决方案是将值装箱,以便它们在收集之前保留在堆上。正确。您可能需要一个
Vec
use std::ptr::read;
use std::mem::forget;

#[repr(C)]
struct Foo {
  id: i32,
  dispose:Option<Box<Fn(Foo) + 'static>> //'
}

impl Foo {
  pub fn new(id:i32) -> Foo {
    return Foo {
        id: id,
        dispose: None
    };
  }
  pub fn release(mut self) {
    if self.dispose.is_some() {
      self.dispose.take().unwrap()(self);
    }
  }
}

impl Drop for Foo {
  fn drop(&mut self) {
    println!("Discarding a foo with dispose of {:?}", self.dispose.is_some());
  }
}

#[repr(C)]
struct Goblin {
  foo:Foo,
  angry: bool,
  friends: i32
}

#[repr(C)]
struct Bat {
  foo:Foo,
  hungry: bool
}

#[repr(C)]
struct Dragon {
  foo:Foo,
  lairs: i32
}

trait IsFoo {
  fn foo(&mut self) -> &mut Foo; 
  fn as_foo<T: IsFoo>(mut self) -> Foo where Self: Sized {
    let ptr:*const Foo = self.foo() as *mut Foo;
    {
        self.foo().dispose = Some(Box::new(|&:foo:Foo| {
          println!("Incoming release for id {}", foo.id);
          unsafe {
            let tmp = &foo as *const Foo as *const T; // Avoid ICE. :(
            let mut instance:T = read::<T>(tmp);
            println!("Dropping instance with id: {}", instance.foo().id);
            drop(instance);
          }
        }));
    }
    unsafe { 
        let rtn = read(ptr);
        forget(self);
        return rtn;
    }
  }
}
impl IsFoo for Bat { fn foo(&mut self) -> &mut Foo { return &mut self.foo; } }
impl IsFoo for Goblin { fn foo(&mut self) -> &mut Foo { return &mut self.foo; } }
impl IsFoo for Dragon { fn foo(&mut self) -> &mut Foo { return &mut self.foo; } }

// Test drops work
impl Drop for Bat { fn drop(&mut self) { println!("Dropped a Bat"); } }
impl Drop for Goblin { fn drop(&mut self) { println!("Dropped a Goblin....!"); } }
impl Drop for Dragon { fn drop(&mut self) { println!("Dropped a Dragon"); } }

fn main() {
  {
    // Generic collection
    let monsters:Vec<Foo> = vec!(
      Bat { foo: Foo::new(1), hungry: true }.as_foo::<Bat>(),
      Goblin { foo: Foo::new(2), angry: true, friends: 100 }.as_foo::<Goblin>(),
      Dragon { foo: Foo::new(3), lairs: 33 }.as_foo::<Dragon>()
    );

    println!("Vector exists without dropping contents");

    // Cleanup
    for m in monsters.into_iter() { 
      println!("Dropping an instance: {}", m.id);
      m.release(); 
    }
  }
}
Vector exists without dropping contents
Dropping an instance: 1
Incoming release for id 1
Dropping instance with id: 1
Discarding a foo with dispose of false
Dropping an instance: 2
Incoming release for id 2
Dropping instance with id: 2
Discarding a foo with dispose of false
Dropping an instance: 3
Incoming release for id 3
Dropping instance with id: 3
Discarding a foo with dispose of false
Vector exists without dropping contents
Dropping an instance: 1
Dropped a Bat
Dropping an instance: 2 <--- WTF, the others work but this one doesn't?
Dropping an instance: 3
Dropped a Dragon