Rust Box<;dyn性状>;解构自己?

Rust Box<;dyn性状>;解构自己?,rust,Rust,因为它不知道数据的具体类型,所以它只包含一个dyn-Trait的vtpr,当它超出范围时,它是如何下降的?Rust中的每个虚拟表是否都包含drop方法实现?当原始框中包含的具体类型未被大小化为特征对象时,该类型的drop实现进入vtable。指针(锈迹中的任何类似指针的东西,即引用、框、原始指针等),其指针对象是特征对象,在内存中的布局如下*: struct FooTraitDynPointer { ptr: *[const/mut] (), vtable: &'stat

因为它不知道数据的具体类型,所以它只包含一个dyn-Trait的vtpr,当它超出范围时,它是如何下降的?Rust中的每个虚拟表是否都包含drop方法实现?

当原始
框中包含的具体类型未被大小化为特征对象时,该类型的
drop
实现进入vtable。指针(锈迹中的任何类似指针的东西,即引用、
框、原始指针等),其指针对象是特征对象,在内存中的布局如下*:

struct FooTraitDynPointer {
    ptr: *[const/mut] (),
    vtable: &'static VTableImplForFooTrait
}
我的示例中的
ptr
字段指向实际数据。我们可以说这是原始的

我的示例中的
vtable
字段指向一个静态vtable。假设我们有以下
Foo
trait:

trait Foo {
    fn bar(&self) -> usize;
}
我们的vtable将如下所示*:

struct VTableImplForFooTrait {
    dropper: unsafe fn(*mut ()),
    size: usize,
    align: usize,
    bar: unsafe fn(*const ()) -> usize,
}
我们看到,
drop
就在那里。除此之外,还有大小和对齐字段,允许拥有的类型释放足够的内存。或者重新分配足够的内存

下面是一个示例程序,它粗略地从指向trait对象的指针中提取结构的大小:

#![feature(raw)]

trait Foo {
    fn bar(&self) -> usize;
}

struct Baz {
    field: f64
}

impl Foo for Baz {
    fn bar(&self) -> usize {
        self.field as usize
    }
}

#[derive(Clone)]
struct FooVTable {
    dropper: unsafe fn(*mut ()),
    size: usize,
    align: usize,
    bar: unsafe fn(*const ()) -> usize,
}

fn main() {
    use std::{mem, raw};
    let value = Baz { field: 20.0 };

    let boxed = Box::new(value) as Box<dyn Foo>;

    let deconstructed: raw::TraitObject = unsafe { mem::transmute(boxed) };

    let vtable = deconstructed.vtable as *mut FooVTable;

    let vtable = unsafe { (*vtable).clone() };

    println!("size: {}, align: {}", vtable.size, vtable.align);

    let result = unsafe { (vtable.bar)(deconstructed.data) };

    println!("Value: {}", result);
}
然而,这很可能会在将来发生变化,所以我在这里留下这个时间戳,供将来在行为发生变化的情况下阅读这篇文章的人使用。2020年6月5日


*:trait对象的布局,尤其是它们的vtable是不能保证的,因此不要依赖于实际代码

size: 8, align: 8
Value: 20