虚表指针在哪里

虚表指针群里有人问。就写了从最简单的类开始, 后面有单继承和多继承虚表指针的不同代码在32环境下:先写结论: 虚表指针在构造函数与析构中赋值(下面反汇编证明), 赋值: *this = 虚表指针(即首个成员) 虚表指针指向的是一个数组,存放虚函数,虚函数按一般声明先后排序. 这个数组一般在 .rdata 或 .data 每个父类都会在构造,析构中设置自己的虚表,下面继承中会写 * 为什么要在构造...
摘要由CSDN通过智能技术生成

虚表指针

群里有人问。就写了

从最简单的类开始, 后面有单继承和多继承虚表指针的不同

代码在32环境下:

先写结论:

         虚表指针在构造函数与析构中赋值(下面反汇编证明), 赋值: *this = 虚表指针(即首个成员)

         虚表指针指向的是一个数组,存放虚函数,虚函数按一般声明先后排序.

         这个数组一般在 .rdata 或 .data

         每个父类都会在构造,析构中设置自己的虚表,下面继承中会写

         单继承: 一个虚表 .  多继承: 有几个父类就有几个虚表

        * 为什么要在构造和析构中都赋值, 在下面的继承中会写.
 

 

下面代码中顺带一些内存布局

虚表指针在构造函数中 *this = 虚表指针, 指向数组[ virtual void t ]

成员变量a 在 this + 4 的地方,跟随在虚表后, 若没有虚表的类则放在this上


#include <iostream>
#include <Windows.h>
#include <stdio.h>
using std::cout;
using std::endl;

class A
{
public:
	A() {		
		a = 1;
	}
	~A() {
	}
	virtual void t() {
		cout << "t" << endl;
	}
	int a;
};

int main()
{
	cout <<"size:" << sizeof(A) << endl;
	A a;
	DWORD * ptr = (DWORD*)&a;
	DWORD vptr_addr = *ptr;
	//虚表在首个成员的地址上 , 即 *this
	cout << "虚表:" << std::hex << vptr_addr<< endl;

	// 因为vptr 占了首个成员的位置, 成员a跟在虚表后面
	int member = *(ptr + 1);
	cout << "member:" << member << endl;

	//通过虚表找到函数地址,只有一个虚函数,因此偏移0
	DWORD * arr_func = (DWORD*)vptr_addr;
	void (*func)() = (void (*)())(*(arr_func + 0)); // arr_func[0]
	cout << "函数地址:" << func << endl;
	func();

	return 0;
}

看反汇编的构造 析构函数 , 删掉了不相关的, 只看虚表指针在构造和析构中赋值:

在这2个函数中赋值都是与继承相关,防止调用错误的虚函数

A(){

mov         dword ptr [this],ecx   // ecx 为 this
mov         eax,dword ptr [this]   // eax = this

// *this =  A的虚表指针 ,这里赋值
mov         dword ptr [eax],offset A::`vftable' (0419B34h) 
    
}

虚表指针: 0x00419B34
内存数据: 0x00419B34  9a 11 41 00 00 00 00 00
还原数组: [0x0041119a] -> [virtual t]


// 在析构中同样出现
~A(){

mov         dword ptr [this],ecx   // ecx == this
mov         eax,dword ptr [this]   // eax = this

// *this = A的虚表指针
mov         dword ptr
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值