C++反汇编-虚函数
在C++中,使用关键字virtual声明为虚函数。
- 虚函数地址表(虚表)
- 定义:当类中定义有虚函数时,编译器会把该类中所有虚函数的首地址保存在一张地址表中,即虚函数地址表。
- 虚表信息在编译后被链接到执行文件中,因此所获得的虚表地址是一个固定的地址。
- 虚表中虚函数的地址排列顺序依据虚函数在类中的声明顺序而定。
- 虚表指针
- 同时编译器还会在类的每个对象添加一个隐藏数据成员,称为虚表指针,保存着虚表的首地址,用于记录和查找虚函数。
- 虚表指针的初始化是通过编译器在构造函数中插入代码实现的。由于必须初始化虚表指针,编译器会提供默认的构造函数。
- 虚函数调用过程
- 虚表间接寻址访问:
使用对象的指针或引用调用虚函数。根据对象的首地址,取出相应的虚表指针,在虚表查找对应的虚函数的首地址,并调用执行。 - 直接调用访问:
使用对象调用虚函数,和调用普通成员函数一样。

- 类中隐式定义一个数据成员
- 数据成员在首地址处,占4字节
- 构造函数初始化该数据成员为某个数组的首地址
- 地址属于数据区,相对固定的地址
- 数组的成员是函数指针
- 函数被调用方式是thiscall
- 构造函数中是完成虚表指针的初始化,此时虚表指针并没有指向虚表函数。
- 执行析构函数时,其对象的虚表指针已经指向某个虚表首地址。虚函数是在还原虚表指针,让其指向自身的虚表首地址,防止在析构函数中调用虚函数时取到非自身虚表。
示例C++源码
1 #include <iostream>
2 using namespace std;
3
4 class CVirtual {
5 public:
6 virtual int GetNumber() { return m_nNumber; }
7 virtual void SetNumber(int nNumber) { m_nNumber = nNumber;}
8 ~CVirtual(){ printf("~CVirtual!"); }
9 private:
int m_nNumber;
};
int main()
{
CVirtual myVirtual ,*pVirtual;
pVirtual = &myVirtual;
pVirtual->SetNumber();
printf("%d\r\n", pVirtual->GetNumber());
return ;
汇编代码
1.构造函数
mov [ebp-], ecx ;=>保存this指针
mov eax, [ebp-] ;=>eax获得this指针
mov dword ptr [eax], offset ??_7CVirtual@@6B@ ; const CVirtual::`vftable' ;=>虚表指针初始化
2.析构函数
mov [ebp-], ecx ;=>保存this指针
mov eax, [ebp-] ;=>eax获得this指针
mov dword ptr [eax], offset ??_7CVirtual@@6B@ ; const CVirtual::`vftable' =>虚表指针重置
push offset aCvirtual ; "~CVirtual!"
3.虚函数调用
pVirtual->SetNumber(10);
push 0Ah ;=>参数10压栈
mov eax, [ebp-18h] ;=>eax为this指针
mov edx, [eax] ;=>edx为虚表指针
mov ecx, [ebp-18h] ;=>ecx传递this指针
mov eax, [edx+] ;=>虚函数SetNumber的地址=虚表+offset 4
call eax
C++反汇编-虚函数的更多相关文章
- C++反汇编第三讲,反汇编中识别虚表指针,以及指向的虚函数地址
C++反汇编第三讲,反汇编中识别虚表指针,以及指向的虚函数地址 讲解之前,了解下什么是虚函数,什么是虚表指针,了解下语法,(也算复习了) 开发知识为了不码字了,找了一篇介绍比较好的,这里我扣过来了,当 ...
- 反汇编->C++虚函数深度分析
先来查看一简单例子 #include<iostream> using namespace std; class Base{ public: virtual void f() { cout ...
- C++反汇编第二讲,反汇编中识别虚表指针,以及指向的虚函数地址
讲解之前,了解下什么是虚函数,什么是虚表指针,了解下语法,(也算复习了) 开发知识为了不码字了,找了一篇介绍比较好的,这里我扣过来了,当然也可以看原博客链接: http://blog.csdn.net ...
- 《C++反汇编与逆向分析技术揭秘》之11——虚函数
虚函数的机制 当类中定义有虚函数时,编译器会将该类中所有虚函数的首地址保存在一张地址表中,这张表被称为虚函数地址表.编译器还会在类中添加一个虚表指针. 举例: CVirtual类的构造函数中没有进行任 ...
- 为何JAVA虚函数(虚方法)会造成父类可以"访问"子类的假象?
首先,来看一个简单的JAVA类,Base. 1 public class Base { 2 String str = "Base string"; 3 protected vo ...
- C++虚函数浅探
C++中和虚函数(Virtual Function)密切相关的概念是"动态绑定"(Dynamic Binding),与之相对的概念是"静态绑定"(Static ...
- C++中的虚函数(表)实现机制以及用C语言对其进行的模拟实现
tfref 前言 C++对象的内存布局 只有数据成员的对象 没有虚函数的对象 拥有仅一个虚函数的对象 拥有多个虚函数的对象 单继承且本身不存在虚函数的继承类的内存布局 本身不存在虚函数(不严谨)但存在 ...
- [置顶] 【C/C++学习】之十三、虚函数剖析
所谓虚函数,虚就虚在“推迟联编”或者“动态联编”上,一个类函数的调用并不是在编译时刻被确定的,而是在运行时刻被确定的.由于编写代码的时候并不能确定被调用的是基类的函数还是哪个派生类的函数,所以被称为“ ...
- C++学习7-面向对象编程基础(多态性与虚函数、 IO文件流操作)
多态 多态性是指对不同类的对象发出相同的消息将返回不同的行为,消息主要是指类的成员函数的调用,不同的行为是指不同的实现: 函数重载 函数重载是多态性的一种简单形式,它是指允许在相同的作用域内,相同的函 ...
随机推荐
- 缓存数据库-redis数据类型和操作(set)
一:Redis 集合(Set) Redis的Set是string类型的无序集合.集合成员是唯一的,这就意味着集合中不能出现重复的数据. Redis 中 集合是通过哈希表实现的,所以添加,删除,查找的复 ...
- python面向对象(六)之元类
元类 1. 类也是对象 在大多数编程语言中,类就是一组用来描述如何生成一个对象的代码段.在Python中这一点仍然成立: In [13]: class ObjectCreator(object): . ...
- Java线程的阻塞
线程的阻塞 线程的优先级 线程总是存在优先级,优先级范围在1~10之间,线程默认优先级是5(数值越大优先级越高): JVM线程调度程序是基于优先级的抢先调度机制: 在大多数情况下,当前运行的线程优先级 ...
- ASP .Net Core系统部署到SUSE 16 Linux Enterprise Server 12 SP2 64 具体方案
.Net Core 部署到 SUSE 16 Linux Enterprise Server 12 SP2 64 位中的步骤 1.安装工具 1.apache 2..Net Core(dotnet-sdk ...
- No.2 selenium学习之路之八种基本定位
selenium的八种定位方式 1.通过id定位 find_element_by_id() send_keys() 输入框输入字符串 click() 鼠标点击事件 注:send_keys输入 ...
- python软件依赖关系
caffe:numpy,scikit-image opencv:numpy
- Java编程思想第四版第二章练习题答案
练习1:创建一个类,它包含一个int域和一个char域,它们都没有被初始化.将他们的值打印出来,以验证Java执行了默认初始化 public class JavaThinking { private ...
- WordPress前台后台出现一片空白的原因以及解决办法
WordPress前台后台出现空白的可能原因有以下: 这个问题,一般是在进行以下操作后出现的: 1.网站更换新主题2.网站安装或升级插件3.升级了Wordpress版本 其实问题的根源在于你的主题.插 ...
- day5模块学习--random模块
Python中的random模块用于生成随机数 下面具体介绍random模块的功能: 1.random.random() #用于生成一个0到1的浮点数 随机浮点数:0<= n < ...
- bzoj 3676 后缀自动机+马拉车+树上倍增
思路:用马拉车把一个串中的回文串个数降到O(n)级别,然后每个串在后缀自动机上倍增找个数. #include<bits/stdc++.h> #define LL long long #de ...