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文件流操作)
多态 多态性是指对不同类的对象发出相同的消息将返回不同的行为,消息主要是指类的成员函数的调用,不同的行为是指不同的实现: 函数重载 函数重载是多态性的一种简单形式,它是指允许在相同的作用域内,相同的函 ...
随机推荐
- HDU 3068 最长回文(manacher模板题)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3068 题目大意:求字符串s中最长的回文子串 解题思路:manacher模板 代码 #include&l ...
- Codeforces 793C - Mice problem(几何)
题目链接:http://codeforces.com/problemset/problem/793/C 题目大意:给你一个捕鼠器坐标,和各个老鼠的的坐标以及相应坐标的移动速度,问你是否存在一个时间点可 ...
- JAVA复习笔记之GC部分
前言:垃圾回收机制,大家都知道JAVA的垃圾回收都是JVM自动回收的,不需要程序员去管理.但是我们还是得知道原理才能在适当时机进行JVM调优 原理:当我们new 一个对象时JVM堆区就会分配一块 ...
- JS中精选this关键字的指向规律你记住了吗
1.首先要明确: 谁最终调用函数,this指向谁 this指向的永远只可能是对象!!!!! this指向谁永远不取决于this写在哪,而取 ...
- 【剑指Offer面试题】 九度OJ1389:变态跳楼梯
转自:http://www.myexception.cn/program/1973966.html 时间限制:1 秒内存限制:32 兆特殊判题:否提交:2331解决:1332 题目描述: 一只青蛙一次 ...
- CCF CSP 201409-4 最优配餐
CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201409-4 最优配餐 问题描述 栋栋最近开了一家餐饮连锁店,提供外卖服务.随着连锁店越来越 ...
- php判断是否是ajax提交 方法
/** * 判断是否是AJAX提交 * @return bool */ function is_ajax() { if(isset($_SERVER['HTTP_X_REQUESTED_WITH']) ...
- linux 101 hacks 3null 改文件大小写 xargs
禁止标准输出和错误信息的输出 当我们调试 shell 脚本的时候,我们往往不希望看到标准输出和标准错误的信息.我们可以使用/dev/nulll 来禁止标准错误的信息. 将标准输出重定向到/dev/nu ...
- 程序设计实习MOOC / 程序设计与算法(三)第一周测验
作业题: 7. 填空(2分)简单的swap 通过码是 ( 请参考公告中的“关于编程作业的说明”完成编程作业(请注意,编程题都要求提交通过码,在openjudge上提交了程序并且通过以后,就可以下载到通 ...
- Java 之 JDBC
mysql : //****** 四大金刚: 驱动类名.url.用户名.密码 //MySQL四大金刚 String driverClassname="com.mysql.jdbc.Drive ...