【问题标题】:Why virtual function's address of virtual table and virtual function's address on class are different?为什么虚表的虚函数地址和类上的虚函数地址不同?
【发布时间】:2021-05-05 14:11:42
【问题描述】:

下面是我的代码

#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <vector>
#include <unordered_set>
#include <deque>
#include <Windows.h>

class B {
private:
    int memB;
public:
    B() :memB(0x11111111) {}
    virtual void f1() { puts("B::f1"); }
    virtual void f2() { puts("B::f2"); }
    virtual void f3() { puts("B::f3"); }
    void normal() { puts("non virtual"); }
};

class D :public B {
private:
    int memD;
public:
    D() :memD(0x22222222) {}
    void f1() { puts("D::f1"); }
    void f2() { puts("D::f2"); }
};

int main() {
    B* pB;
    B b;
    D d;

    pB = &b;
    pB->f1();
    pB->f2();
    pB->f3();
    
    pB = &d;
    pB->f1();
    pB->f2();
    pB->f3();

    return 0;
}

以上是我的结果图片。

如您所见,B::f1 和 b.__vfptr[0](指向 B::f1)的地址不同。

我认为它们会相同,因为它们指向相同的函数 'B:: f1'。

为什么他们的地址不同?

期待您的精彩回答。

感谢您的阅读。

【问题讨论】:

    标签: c++ virtual-functions


    【解决方案1】:

    在 x86(32 位)调试模式下,MSVC vtable 条目指向函数蹦床,其中包含指向实际虚拟函数的 JMP 指令。

    如果你打开反汇编窗口并从vtable输入地址(例如0xb61276),你可以很容易地看到它:

    B::f1:
    00B61276  jmp         B::f1 (0B61970h)  
    

    大概是为了方便设置软件断点。

    在 x86 Release 或 64 位模式下不是这种情况(可能是因为在 64 位模式下 MSVC 调试器总是使用硬件断点)。

    【讨论】:

      猜你喜欢
      • 2014-06-02
      • 1970-01-01
      • 2016-10-05
      • 1970-01-01
      • 2011-01-11
      • 2011-03-05
      • 1970-01-01
      • 2011-12-11
      • 1970-01-01
      相关资源
      最近更新 更多