简体   繁体   English

盒子如何<dyn trait>解构自己?</dyn>

[英]How does Box<dyn Trait> deconstruct itself?

Since it doesn't know the concrete type of the data, it only contains a vtpr of dyn Trait, How does it drop itself when it goes out of scope?由于它不知道数据的具体类型,它只包含一个dyn Trait的vtpr,当它从scope出来时,它是如何掉线的? Does every virtual table in Rust contains a drop method implementation? Rust 中的每个虚拟表是否都包含删除方法实现?

When the concrete type the original Box contained is unsized into a trait object, the Drop implementation for the type goes into the vtable.当原始Box包含的具体类型未调整大小为特征 object 时,该类型的Drop实现进入 vtable。 A pointer (Any pointer-like thing in Rust. IE, a reference, Box , raw pointer, etc.) whose pointee is a trait object is laid out as follows in memory*:指针(Rust.IE、引用、Box、原始指针等)的指针(Rust.IE、引用、 Box 、原始指针等)的指针是特征 object 在内存中的布局如下*:

struct FooTraitDynPointer {
    ptr: *[const/mut] (),
    vtable: &'static VTableImplForFooTrait
}

The ptr field in my example points to the actual data.我示例中的ptr字段指向实际数据。 We could say that's the original Box .我们可以说那是原始的Box

The vtable field in my example points to a static vtable.我的示例中的vtable字段指向 static vtable。 Say we have the following Foo trait:假设我们有以下Foo特征:

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

Our vtable will look as follows*:我们的 vtable 如下所示*:

struct VTableImplForFooTrait {
    dropper: unsafe fn(*mut ()),
    size: usize,
    align: usize,
    bar: unsafe fn(*const ()) -> usize,
}

We see there, that the drop is there.我们在那里看到, drop在那里。 Along with it, there're size and align fields which allow owning types to deallocate enough memory.除此之外,还有大小和对齐字段,允许拥有类型释放足够的 memory。 Or re-allocate enough memory.或者重新分配足够的memory。

Here's an example program which crudely extracts the size of a struct from within a pointer to a trait object:这是一个示例程序,它从指向特征 object 的指针中粗略地提取结构的大小:

#![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);
}

Playground 操场

(Currently) prints: (当前)打印:

size: 8, align: 8
Value: 20

However this may very well change in the future so I'm leaving this timestamp here for someone who reads this in a future where the behaviour has been changed.然而,这在未来很可能会发生变化,所以我将把这个时间戳留给那些在未来阅读这个行为已经改变的人。 June 5, 2020. 2020 年 6 月 5 日。


*: The layout of trait objects, and especially their vtables is NOT guaranteed, so do not rely in actual code. *:不能保证 trait 对象的布局,尤其是它们的 vtables,所以不要依赖于实际代码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何将接口 function 消耗自身的动态特征装箱? - How to box a dyn trait with interface function consume itself? 你如何转换一个盒子<dyn trait>到 Rc<dyn trait> ?</dyn></dyn> - How do you convert a Box<dyn Trait> to a Rc<dyn Trait>? 创建 Box 时如何转换为 dyn Trait<dyn trait></dyn> - How to cast to dyn Trait when creating a Box<dyn Trait> 如何移动 Vec <box<dyn trait> &gt; 走进 Vec <rc<refcell<dyn trait> &gt;&gt; </rc<refcell<dyn></box<dyn> - How to move a Vec<Box<dyn Trait>> Into Vec<Rc<RefCell<dyn Trait>>> 返回对 Box 的引用<dyn trait></dyn> - Returning a reference to a Box<dyn Trait> `Box` 是否掩盖了特征界限? 在这种情况下,为什么我可以将 `dyn FnOnce()` 分配给 `dyn Fn()`? - Does `Box` obscure trait bounds? Why can i assign `dyn FnOnce()` to `dyn Fn()` in this case? 如何克隆 Vec <Box<dyn Trait> &gt;? - How can I clone a Vec<Box<dyn Trait>>? 如何克隆盒装特征错误(框<dyn error> )?</dyn> - How to clone a boxed trait Error ( Box<dyn Error> )? 为什么“ impl Trait”返回值实现“ Box时发送” <dyn Trait> `不是吗? - Why does an `impl Trait` return value implement Send while `Box<dyn Trait>` does not? 为什么特征类型为`Box<dyn error> ` 错误“未实现大小”但 `async fn() -&gt; Result&lt;(), Box<dyn error> &gt;` 有效吗?</dyn></dyn> - Why does a trait type `Box<dyn Error>` error with "Sized is not implemented" but `async fn() -> Result<(), Box<dyn Error>>` works?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM