先来查看一简单例子
    1. #include<iostream>
    1. using namespace std;
    1. class Base{
    1. public:
    1. virtual void f() { cout << "base f()被call"<<endl; }
    1. virtual void g() { cout << "父类虚函数G被call" << endl; }
    1. };
    1. class Derive : public Base{
    1. public:
    1. virtual void f() { cout << "子类虚函数f()被call" << endl; }
    1. };
    1. int main()
    1. {
    1. Derive d; //子类对象
    1. Base *pb;//父类指针
    1. pb = &d;//父类指针指向子类对象
    1. int *q =(int*) pb;//取出类对象地址
    1. void(*f)(Derive*) = (void(*)(Derive*))(*(int*)(*q));//取出f()函数地址
    1. void(*g)(Derive*) = (void(*)(Derive*))(*(int*)(*q+4));//取出g()函数地址
    1. f((Derive*)pb);//调用子对象虚函数表的第一个元素
    1. g((Derive*)pb);//调用子对象虚函数表的第二个元素
    1. system("pause");
    1. return 0;
    1. }
用VS2015调试一番.查看pb保存子对象的地址.

 以上pb保存了子类对象的地址,地址为0x003bfb64.来看看.这个子类对象的首4个字节(32位机子)地址保存了啥内容(其实是虚函数表的地址)
 .

子类对象首4个字节保存了00948b34这个数值.(这个其实是虚函数表的地址).再来看看这个数值保存了啥内容.

 发现这个地址开始 0094142e跟00941424应该就是虚函数的地址了.不信.咋们到反汇编查看该地址内容.

先查看0x0094142e(函数转为反汇编.其实第一个地址就是跳转).发现没.反汇编已经提示了是Derive::f这个函数
再看看0x00941424.是Base::g这个函数
以上可知.一般编译器实现.把虚函数表的地址用放在子对象首4个字节.虚函数表保存的是虚函数的地址.
  1. void(*f)(Derive*) = (void(*)(Derive*))(*(int*)(*q));//取出f()函数地址
  2. void(*g)(Derive*) = (void(*)(Derive*))(*(int*)(*q+4));//取出g()函数地

比如以上2行.q是子对象的地址.(*q)就是虚函数表的地址 (*q)+4 相当于虚函数的第二个元素的地址. *(int*)(*q)表示第一个虚函数的地址.*(int*)(*q+4));表示第二个虚函数表的地址..最后强制转换为类成员函数.用(void(*)(Derive*).因为一般类成员函数在编译后.首形参是一个this指针.这里用Derive*.因为this指针的类型就是类的类型
  1. f((Derive*)pb);//调用子对象虚函数表的第一个元素
  2. g((Derive*)pb);//调用子对象虚函数表的第二个元素

 最后调用这2个虚函数表中的虚函数.把pb(子对象的地址)当做参数this指针.然后直接调用.即可使得函数被调用了
 
 

 







反汇编->C++虚函数深度分析的更多相关文章

  1. 《C++反汇编与逆向分析技术揭秘》之11——虚函数

    虚函数的机制 当类中定义有虚函数时,编译器会将该类中所有虚函数的首地址保存在一张地址表中,这张表被称为虚函数地址表.编译器还会在类中添加一个虚表指针. 举例: CVirtual类的构造函数中没有进行任 ...

  2. C++反汇编-虚函数

    学无止尽,积土成山,积水成渊-<C++反汇编与逆向分析技术揭秘> 读书笔记 在C++中,使用关键字virtual声明为虚函数. 虚函数地址表(虚表) 定义:当类中定义有虚函数时,编译器会把 ...

  3. C++ 虚函数在基类与派生类对象间的表现及其分析

    近来看了侯捷的<深入浅出MFC>,读到C++重要性质中的虚函数与多态那部分内容时,顿时有了疑惑.因为书中说了这么一句:使用“基类之指针”指向“派生类之对象”,由该指针只能调用基类所定义的函 ...

  4. 从汇编层面深度剖析C++虚函数

    文章出处:http://blog.csdn.net/linyt/article/details/6336762 虚函数是C++语言实现运行时多态的唯一手段,因此掌握C++虚函数也成为C++程序员是否合 ...

  5. RTTI、虚函数和虚基类的实现方式、开销分析及使用指导(虚函数的开销很小,就2次操作而已)

    白杨 http://baiy.cn “在正确的场合使用恰当的特性” 对称职的C++程序员来说是一个基本标准.想要做到这点,首先要了解语言中每个特性的实现方式及其开销.本文主要讨论相对于传统 C 而言, ...

  6. 类虚函数表原理实现分析(当我们将虚表地址[n]中的函数替换,那么虚函数的实现就由我们来控制了)

    原理分析 当调用一个虚函数时, 编译器生成的代码会调用 虚表地址[0](param1, param2)这样的函数. 已经不是在调用函数名了. 当我们将虚表地址[n]中的函数实现改为另外的函数, 虚函数 ...

  7. C++反汇编第三讲,反汇编中识别虚表指针,以及指向的虚函数地址

    C++反汇编第三讲,反汇编中识别虚表指针,以及指向的虚函数地址 讲解之前,了解下什么是虚函数,什么是虚表指针,了解下语法,(也算复习了) 开发知识为了不码字了,找了一篇介绍比较好的,这里我扣过来了,当 ...

  8. 31.C++-虚函数之构造函数与析构函数分析

    1.构造函数不能为虚函数 当我们将构造函数定义为虚函数时,会直接报错: 首先回忆下以前学的virtual虚函数概念: 如果类定义了虚函数,创建对象时,则会分配内存空间,并且为该父类以及其所有子类的内存 ...

  9. C++反汇编第二讲,反汇编中识别虚表指针,以及指向的虚函数地址

    讲解之前,了解下什么是虚函数,什么是虚表指针,了解下语法,(也算复习了) 开发知识为了不码字了,找了一篇介绍比较好的,这里我扣过来了,当然也可以看原博客链接: http://blog.csdn.net ...

随机推荐

  1. 洛谷 1571 眼红的Medusa

    洛谷 1571 眼红的Medusa 虽说这道题标签里写明了二分,然而我还是首先想到了map......毕竟map真的是简单好写. map做法 #include<bits/stdc++.h> ...

  2. apply 与 lambda

    Python中的lambda和apply用法  https://blog.csdn.net/anshuai_aw1/article/details/82347016

  3. mysql Plugin ‘InnoDB’ init function returned error

    问题描述: 非正常关闭mysql,同时更改了my.cnf 导致启动时不支持innodb,出现如下错误:   [ERROR] Plugin ‘InnoDB’ init function returned ...

  4. cento命令之which、whereis、locate、find

    [which] 查看可执行文件的位置 语法: [root@localhost ~]# which 可执行文件名称 例如: [root@localhost ~]# which passwd /usr/b ...

  5. UVa 10564 DP Paths through the Hourglass

    从下往上DP,d(i, j, k)表示第(i, j)个格子走到底和为k的路径条数. 至于字典序最小,DP的时候记录一下路径就好. #include <cstdio> #include &l ...

  6. 【15】ES6 for Humans: The Latest Standard of JavaScript: ES2015 and Beyond

    [15]ES6 for Humans 共148页: 目前看到:已经全部阅读.   亚马逊地址: 魔芋:总结: 我先看的是阮一峰的在线书籍.这本书的内容很多都与之重复的. 居然卖¥463.也是没谁了. ...

  7. javascript常见数据集

    目录 数组 对象 一.数组 创建方法 1 2 3 var arrayObj = new Array(); //创建一个数组             var arrayObj = new Array([ ...

  8. Vue简单了解

    目录 1. 前端概览 2. 现代前端开发方式 3. MVVM开发核心 4. Vue核心 5. Vue优点 6. Vue难点 7. Vue与非Vue项目结合 8. Vue调试 9. Vue与SEO 今天 ...

  9. 大数据学习——scala的wordCount小例子

    val lines=List("hello tom hello jerry","hello tom hello kitty hello china") //方法 ...

  10. adb devices 找不到夜神模拟器解决方法

    先打开命令行窗口,输入adb devices,查看连接信息,大致意思是sdk的adb版本与夜神的adb版本不一致,导致. C:\Users\cz9025>adb devices List of ...