【问题标题】:Runtime introspection in C++ - How does it work internally?C++ 中的运行时自省 - 它是如何在内部工作的?
【发布时间】:2021-12-02 04:00:08
【问题描述】:

我正在寻找有关 C++ 中运行时自省如何工作的信息。

到目前为止,我发现附加信息将存储为每种类型的运行时类型信息 (RTTI)。我找不到这些信息以什么形式存储或如何检查或访问。

想想如果我们有两种非常相似的类型,内省是如何工作的,例如:

class TypeOne {
  string name;
}

class TypeTwo {
  string name;
}

哪些信息会准确地存储在内存中,以便我们通过自省来区分这两种类型?

TL;DR 寻找有关如何实施自省的更多信息。

编辑 1: 让我们明确一点,我不需要知道如何使用自省,而是知道它是如何实现的。编译器如何生成 RTTI 信息?它是按每个实例化的对象存储的吗?最后在运行时如何比较 RTTI?

【问题讨论】:

  • 这能回答你的问题吗? C++: type_info to distinguish types
  • 没有读取类型信息。请提供相关示例。
  • 您需要检查工具链的源代码 - "...type_info 类包含有关类型的实现特定信息, ..." - en.cppreference.com/w/cpp/types/type_info
  • @ l000p 你是在问为什么编译器知道typeid(TypeOne) 应该为TypeOne 而不是TypeTwo 返回type_info?你认为编译器很难做什么?
  • 对于这些类型,编译器甚至不会进行运行时自省。它只会在编译时直接链接到硬编码的type_info。您的样本不会涉及任何 RTTI。

标签: c++ class introspection


【解决方案1】:

至少对于 g++,通过查看生成的汇编代码很容易了解 typeinfo 是如何实现的。对于这样的程序:

#include <typeinfo>
#include <stdio.h>

int main() {
    printf("%p\n", &typeid(main));
}

你得到

        .weak   _ZTSFivE
        .section        .rodata._ZTSFivE,"aG",@progbits,_ZTSFivE,comdat
        .type   _ZTSFivE, @object
        .size   _ZTSFivE, 5
_ZTSFivE:
        .string "FivE"
        .weak   _ZTIFivE
        .section        .data.rel.ro._ZTIFivE,"awG",@progbits,_ZTIFivE,comdat
        .align 8
        .type   _ZTIFivE, @object
        .size   _ZTIFivE, 16
_ZTIFivE:
        .quad   _ZTVN10__cxxabiv120__function_type_infoE+16
        .quad   _ZTSFivE

因此,对于此处的 typeid,它在“comdat”部分创建了一个带有弱符号的小型(2 字)只读对象,以及一个看起来像错位名称的字符串(也是一个弱符号)。这意味着如果在多个编译单元中创建同一个对象,它们将被组合成一个公共对象。因此,对于程序中任何地方用 typeid 引用的每种不同类型,您最终都会得到一个 typeinfo 对象。

其他实现可能不同。

【讨论】:

    猜你喜欢
    • 2018-09-30
    • 2019-10-16
    • 2011-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-08
    • 2011-05-24
    相关资源
    最近更新 更多