为什么virtualtable上的虚函数地址和class上的虚函数地址不一样?
Why virtual function's address of virtual table and virtual function's address on class are different?
下面是我的代码
#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'。
为什么他们的地址不同?
期待您的精彩回答。
感谢您的阅读。
在 x86(32 位)调试模式下,MSVC vtable 条目指向函数 trampoline,其中包含指向实际虚拟函数的 JMP 指令。
打开反汇编window,输入vtable中的地址(如0xb61276
)即可轻松看到:
B::f1:
00B61276 jmp B::f1 (0B61970h)
估计是为了方便设置软件断点。
在 x86 Release 或 64 位模式下不是这种情况(可能是因为在 64 位模式下 MSVC 调试器总是使用硬件断点)。
下面是我的代码
#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'。
为什么他们的地址不同?
期待您的精彩回答。
感谢您的阅读。
在 x86(32 位)调试模式下,MSVC vtable 条目指向函数 trampoline,其中包含指向实际虚拟函数的 JMP 指令。
打开反汇编window,输入vtable中的地址(如0xb61276
)即可轻松看到:
B::f1:
00B61276 jmp B::f1 (0B61970h)
估计是为了方便设置软件断点。
在 x86 Release 或 64 位模式下不是这种情况(可能是因为在 64 位模式下 MSVC 调试器总是使用硬件断点)。