[英]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.