【问题标题】:Address of the object - void* and void**对象的地址 - void* 和 void**
【发布时间】:2019-11-23 03:51:31
【问题描述】:

我试图获取存储在 y 中的 vtable 地址,但我不明白为什么 x 包含不同的地址。

#include <iostream>
class A {
    public:
        virtual int f() {
            return 2;
        }
};


int main() {
    A obj;
    void* x = (void**)&obj;
    void* y = *((void**)&obj);

    std :: cout << x << std :: endl;
    std :: cout << y << std :: endl;

    void** vtable = (void**)y;
    std :: cout << ((int(*)())(vtable[0]))() << std :: endl;

}

【问题讨论】:

  • 首先:这太疯狂了,尤其是函数调用。 mo 保证存在与成员函数(虚函数或其他函数)兼容的 任何 函数指针类型。
  • xobj 的地址——(void**) 无关紧要。 y 是一个“正确的”类型双关语(并且是未定义的行为)。
  • 为什么你认为(void**)&amp;obj*((void**)&amp;obj) 会是同一个地址?也许我完全误解了。
  • 我不明白为什么在那个双关语之后我在 Y 中有一个 vtable 地址。
  • 这里有很多 UB。

标签: c++ memory function-pointers void-pointers virtual-functions


【解决方案1】:

这都是未定义的行为,但以下代码将为您提供该 vtable 地址:

A obj;
void **vtable = * (void ***) &obj;

对 vtable 的布局做一些假设,我们可以证明是这样的:

#include <iostream>

class A
{
public:
    virtual void f () { }
};


int main() {
    A obj;
    void **vtable = * (void ***) &obj;
    std :: cout << vtable << std :: endl;
    std :: cout << *vtable << std :: endl;
    std :: cout << (void *) &A::f << std :: endl;
}

输出:

0x400e88
0x400de4
0x400de4

多重和/或虚拟继承会使这更难做到。

Live demo

【讨论】:

  • 那是演员标准吗?
猜你喜欢
  • 2020-04-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-14
  • 2021-08-06
  • 2022-12-07
  • 1970-01-01
相关资源
最近更新 更多