【问题标题】:How to get the base class offset of an inherited struct without creating an instance如何在不创建实例的情况下获取继承结构的基类偏移量
【发布时间】:2022-01-03 22:36:48
【问题描述】:

考虑以下代码:

struct A {
    int64 member;
    int32 member2;
    virtual void f();
};

struct B {
    int16 member3;

    virtual void b();
};

struct C : A, B {
    virtual void b() override;
};

我有兴趣在C 中找到B 的偏移量。以前使用其他没有虚拟继承的结构,并且第一个成员只有一个基类offsetof 似乎可以工作。我已经反编译了一些代码(在 IDA 中)并且基类在这里很好地突出显示(十六进制):

在函数中,通过将偏移量添加到void*(通过转换为char*),这些精确的基类偏移量用于将void* 转换为派生类。结构体ABC与编译后的代码中的结构体类似,包括具有虚函数的类和多个基类。

我的问题是他们是怎么做到的,我该怎么做?我尝试过类似i32 offset = (i64)((B*)((C*)NULL)); 但没有运气。

【问题讨论】:

  • “虚拟基类”没有出现在这里。你有虚拟成员的基地,而不是虚拟基地。如果您有虚拟基地,答案将是“没有唯一的答案”
  • 谁是“他们”,他们是否有权访问该程序的调试符号?
  • 你的权利,意思是虚拟成员函数。它是一个游戏引擎,是的,因为如果这就是你的意思,我有 PDB。查找偏移量的代码将在编译时生成,因为我可以在可执行文件的数据段中看到原始偏移量

标签: c++ class virtual-table


【解决方案1】:

我尝试了以下方法,并且成功了:

(char*)(B*)(C*)0x100 - (char*)(C*)0x100

它将C* 转换为B*;这应该可以完成工作。其余的都是支持。我使用了任意数字0x100;它似乎适用于除 0 以外的所有数字。

为什么它对 0 不起作用:它看到了一个 C* 类型的空指针;要将其转换为B* 类型的空指针,它仍应为空。一种特殊情况。

当然,这使用了未定义的行为。在我的简短测试程序中,它似乎在 Visual Studio 中工作;不保证它可以在其他任何地方工作。

【讨论】:

  • 完美,工作!非常感谢,令人沮丧的是它只是因为它是空的,但我看到编译器会尝试优化它,因为它看到它是一个空常量
  • 不是因为优化。如果强制转换空指针会给我们一个非空指针,那就太可怕了。那么在强制转换之后就不可能处理无效指针了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-24
相关资源
最近更新 更多