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文件流操作)
多态 多态性是指对不同类的对象发出相同的消息将返回不同的行为,消息主要是指类的成员函数的调用,不同的行为是指不同的实现: 函数重载 函数重载是多态性的一种简单形式,它是指允许在相同的作用域内,相同的函 ...
随机推荐
- http://code52.org/DownmarkerWPF/
http://code52.org/DownmarkerWPF/ http://kb.cnblogs.com/page/132209/
- java基础58 JavaScript的几种格式和变量的声明方式(网页知识)
1.JavaScript的几种格式 1.1.JavaScript的特点 1.跨平台性 2.安全性.(javaScript代码不能直接访问电脑硬盘上的信息) 1.2.Java与javaScript ...
- java基础49 IO流技术(对象输入流/对象输出流)
1.对象输入输出流 对象注意作用是用于写对象信息与读取对象信息 1.对象输出流:ObjectOutputStream 2.对象输入流:ObjectInputStream 2.对象输入输出流的步骤 ...
- ROS + Caffe 机器人操作系统框架和深度学习框架笔记 (機器人控制與人工智能)
ROS + Caffe,这里以环境中物体识别为示例,机器人怎么知道环境里面有什么呢? [0.0567392 - n03376595 folding chair][0.0566773 - n040999 ...
- yum安装Mysql-5.6
MySQL yum库提供了一个简单的和方便的方法来安装和更新MySQL相关的软件包到最新版本. MySQL yum库文档说明:http://dev.mysql.com/doc/mysql-yum-re ...
- hdu 3389 阶梯博弈
题意:1-N带编号的盒子,当编号满足A>B && A非空 && (A + B) % 3 == 0 && (A + B) % 2 == 1则可以从A ...
- Kafka(三)Kafka的高可用与生产消费过程解析
一 Kafka HA设计解析 1.1 为何需要Replication 在Kafka在0.8以前的版本中,是没有Replication的,一旦某一个Broker宕机,则其上所有的Partition数据 ...
- 【LOJ】 #2025. 「JLOI / SHOI2016」方
题解 有什么LNOI啊,最后都是JLOI罢了 一道非常--懵逼的统计题 当然是容斥,所有的方案 - 至少有一个点坏掉的正方形 + 至少有两个点坏掉的正方形 - 至少有三个点坏掉的正方形 + 至少有四个 ...
- JSP的学习三(中文乱码)
1). 在 JSP 页面上输入中文, 请求页面后不出现乱码: 保证 contentType="text/html; charset=UTF-8", pageEncoding=&qu ...
- hdoj2191 珍惜现在,感恩生活(01背包 || 多重背包)
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=2191 思路 由于每种大米可能不止一袋,所以是多重背包问题,可以直接使用解决多重背包问题的方法,也可以将 ...