簡體   English   中英

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

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

由於它不知道數據的具體類型,它只包含一個dyn Trait的vtpr,當它從scope出來時,它是如何掉線的? Rust 中的每個虛擬表是否都包含刪除方法實現?

當原始Box包含的具體類型未調整大小為特征 object 時,該類型的Drop實現進入 vtable。 指針(Rust.IE、引用、Box、原始指針等)的指針(Rust.IE、引用、 Box 、原始指針等)的指針是特征 object 在內存中的布局如下*:

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

我示例中的ptr字段指向實際數據。 我們可以說那是原始的Box

我的示例中的vtable字段指向 static vtable。 假設我們有以下Foo特征:

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

我們的 vtable 如下所示*:

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

我們在那里看到, drop在那里。 除此之外,還有大小和對齊字段,允許擁有類型釋放足夠的 memory。 或者重新分配足夠的memory。

這是一個示例程序,它從指向特征 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);
}

操場

(當前)打印:

size: 8, align: 8
Value: 20

然而,這在未來很可能會發生變化,所以我將把這個時間戳留給那些在未來閱讀這個行為已經改變的人。 2020 年 6 月 5 日。


*:不能保證 trait 對象的布局,尤其是它們的 vtables,所以不要依賴於實際代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM