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? Does every virtual table in Rust contains a drop method implementation?
When the concrete type the original Box
contained is unsized into a trait object, the Drop
implementation for the type goes into the 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*:
struct FooTraitDynPointer {
ptr: *[const/mut] (),
vtable: &'static VTableImplForFooTrait
}
The ptr
field in my example points to the actual data. We could say that's the original Box
.
The vtable
field in my example points to a static vtable. Say we have the following Foo
trait:
trait Foo {
fn bar(&self) -> usize;
}
Our vtable will look as follows*:
struct VTableImplForFooTrait {
dropper: unsafe fn(*mut ()),
size: usize,
align: usize,
bar: unsafe fn(*const ()) -> usize,
}
We see there, that the drop
is there. Along with it, there're size and align fields which allow owning types to deallocate enough memory. Or re-allocate enough memory.
Here's an example program which crudely extracts the size of a struct from within a pointer to a trait 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);
}
(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.
*: The layout of trait objects, and especially their vtables is NOT guaranteed, so do not rely in actual code.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.