rust - 如何在下降时更改值?

标签 rust

我目前正在尝试了解 drop 的工作原理。下面的代码崩溃了,我不明白为什么。根据我的理解,std::ptr::write 的使用应该阻止析构函数(编辑:原始值,这里:Rc)运行(在这种情况下,除了内存之外应该没有什么不好的事情发生泄露)。但它似乎并没有那样做( playpen ,用 -O0 编译)

use std::rc::Rc;
use std::mem;
use std::ptr;

enum Foo {
    Bar(Rc<usize>),
    Baz
}
use Foo::*;

impl Drop for Foo {
    fn drop(&mut self) {
        match *self {
            Bar(_) => {
                unsafe { ptr::write(self, Foo::Baz) }
                //unsafe { mem::forget(mem::replace(self, Foo::Baz)) }
            }
            Baz => ()
        }
    }
}

fn main() {
    let _ = Foo::Bar(Rc::new(23));
}

给出溢出错误:

thread '<main>' panicked at 'arithmetic operation overflowed', /Users/rustbuild/src/rust-buildbot/slave/nightly-dist-rustc-mac/build/src/liballoc/rc.rs:755

另一个变体以非法指令退出。为什么会这样?如何将 self 替换为将被正确删除的值?

最佳答案

我还不确定如何实现你的目标,但是我可以证明这一点

From my understanding, the usage of std::ptr::write should prevent the destructor from running

不正确:

use std::mem;
use std::ptr;

struct Noisy;
impl Drop for Noisy {
    fn drop(&mut self) { println!("Dropping!") }
}

enum Foo {
    Bar(Noisy),
    Baz
}
use Foo::*;

impl Drop for Foo {
    fn drop(&mut self) {
        println!("1");

        match self {
            &mut Bar(_) => {
                println!("2");
                unsafe { ptr::write(self, Foo::Baz) }
                println!("3");
            }
            &mut Baz => {
                println!("4");
            }
        }

        println!("5");
    }
}

fn main() {
    let _ = Foo::Bar(Noisy);
}

这打印:

1
2
3
5
Dropping!

说明Foo::Bar的析构函数还在运行,包括Noisy的析构函数。

一个潜在的解决方案是使用 Option::take :

use std::mem;

struct Noisy;
impl Drop for Noisy {
    fn drop(&mut self) { println!("Dropping!") }
}

enum Foo {
    Bar(Option<Noisy>),
    Baz
}

impl Drop for Foo {
    fn drop(&mut self) {
        match *self {
            Foo::Bar(ref mut x) => {
                unsafe { mem::forget(x.take()) }
            }
            Foo::Baz => {}
        }
    }
}

fn main() {
    let _ = Foo::Bar(Some(Noisy));
}

关于rust - 如何在下降时更改值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29196869/

相关文章:

rust - 值移到这里,在循环的前一次迭代中

multithreading - 在采用 `&mut self`(如 drop)的方法中加入线程会导致 "cannot move out of borrowed content"

rust - 如何在稳定的 Rust 中分配原始可变指针?

rust - 如何使用 `into_boxed()` 构建过滤表达式来针对带有联接的查询进行操作?

linker - 构建用于Nordic SDK程序的静态rust库时多次定义 `memset'

rust - 什么是有和无?

rust - 乘法时移动值

rest - 为什么warp对于错误键入的参数返回“HTTP 405方法不允许”?

rust - 为什么 `&str` 实现函数(例如 `String` )的 `String::trim` 结果不像静态字符串文字?

vector - 有没有办法获取向量的每个 n * i 元素?