【问题标题】:Are vtables generated for all types that implement a trait?是否为所有实现 trait 的类型生成了 vtable?
【发布时间】:2021-10-14 16:59:30
【问题描述】:

如果我有一个特征Foo,以及一些实现者BarBaz

impl Foo for Bar {
}
impl Foo for Baz {
}

但是假设我只使用其中一个作为特征对象,

let bar = Bar {..};
let foo: &dyn Foo = &bar;

那么我的二进制文件是否仍然具有两者的 vtable? 这种行为在调试版本和发布版本之间会发生变化吗?

【问题讨论】:

    标签: rust traits vtable trait-objects


    【解决方案1】:

    让我们找出答案。我把这个类似的代码in the Rust Playground 并运行“显示程序集”:

    trait Foo {
        fn x(&self);
    }
    impl Foo for u8 {
        fn x(&self) {
            dbg!("xu8");
        }
    }
    impl Foo for u16 {
        fn x(&self) {
            dbg!("xu16");
        }
    }
    
    fn main() {
        let foo: &dyn Foo = &123_u8;
        foo.x();
        123_u8.x();
        123_u16.x();
    }
    

    在(调试模式)程序集输出中,main 是:

    playground::main:
        subq    $24, %rsp
        leaq    .L__unnamed_12(%rip), %rax
        movq    %rax, 8(%rsp)
        leaq    .L__unnamed_2(%rip), %rax
        movq    %rax, 16(%rsp)
        leaq    .L__unnamed_12(%rip), %rdi
        callq   *.L__unnamed_2+24(%rip)
        leaq    .L__unnamed_12(%rip), %rdi
        callq   <u8 as playground::Foo>::x
        leaq    .L__unnamed_13(%rip), %rdi
        callq   <u16 as playground::Foo>::x
        addq    $24, %rsp
        retq
    

    我们不需要看懂 x86 汇编的每一个细节就可以看到这里有三个函数调用,最后两个是我添加的静态调用进行比较。所以,.L__unnamed_2 可能与 vtable 有关。那是什么?

    .L__unnamed_2:
        .quad   core::ptr::drop_in_place<u8>
        .asciz  "\001\000\000\000\000\000\000\000\001\000\000\000\000\000\000"
        .quad   <u8 as playground::Foo>::x
    

    对我来说看起来像一个 vtable:它指的是滴胶和 x() 的实现。但是对于u16 没有任何相同的作用——对&lt;u16 as playground::Foo&gt;::x 的唯一引用是main 中的静态调度调用。

    当然,这不排除编译器生成了 vtable 数据,然后在进入汇编列表之前将其丢弃。但如果是这样,那要么是编译器性能错误,要么成本太低以至于不值得担心。

    (另外,作为更多轶事证据:如果碰巧在单独的代码生成单元中需要它们,Rust 编译器是 known to generate multiple vtables for the same type。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-31
      相关资源
      最近更新 更多