gpt4 book ai didi

rust - Box 如何 self 解构?

转载 作者:行者123 更新时间:2023-12-03 11:24:47 24 4
gpt4 key购买 nike

由于它不知道数据的具体类型,它只包含一个 dyn Trait 的 vtpr,当它超出范围时它是如何丢弃自己的? Rust 中的每个虚拟表都包含一个 drop 方法实现吗?

最佳答案

当具体类型原Box包含的大小未调整为特征对象,Drop该类型的实现进入 vtable。一个指针(Rust 中的任何类似指针的东西。IE,一个引用,Box,原始指针等)的指针是一个 trait 对象,它在内存中的布局如下*:

struct FooTraitDynPointer {
ptr: *[const/mut] (),
vtable: &'static VTableImplForFooTrait
}
ptr我的示例中的字段指向实际数据。我们可以说这是原来的 Box .
vtable我的示例中的字段指向静态 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在那儿。除此之外,还有 size 和 align 字段,它们允许拥​​有的类型释放足够的内存。或者重新分配足够的内存。

这是一个示例程序,它从指向 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);
}

Playground

(当前)打印:
size: 8, align: 8
Value: 20

但是,这在 future 很可能会发生变化,所以我将这个时间戳留在这里,供将来阅读此行为已更改的人使用。 2020 年 6 月 5 日。

*: trait 对象的布局,尤其是它们的 vtables 是 不是 保证,所以不要依赖于实际代码。

关于rust - Box<dyn Trait> 如何 self 解构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62207849/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com