获取C++虚表地址和虚函数地址

获取C++虚表地址和虚函数地址

By qianghaohao

学过C++的应该都对虚表有所耳闻,在此就不过多介绍概念了,通过实

例来演示一下如何获取虚表地址和虚函数地址。

简单说一下虚表的概念:在一个类中如果有虚函数,那么此类的实例中就有

一个虚表指针指向虚表,这个虚表是一块儿专门存放类的虚函数地址的内存。

图示说明本文的主题(先看图更容易后面代码中的指针操作):

代码如下(要讲解的都在代码的注释中说明了):

class Base {
public:
    virtual void f() { cout << "Base::f" << endl; }
    virtual void g() { cout << "Base::g" << endl; }
    void h() { cout << "Base::h" << endl; }
};

typedef void(*Fun)(void);  //函数指针
int main()
{
    Base b;
    //  这里指针操作比较混乱,在此稍微解析下:

    //  *****printf("虚表地址:%p\n", *(int *)&b); 解析*****:
    //  1.&b代表对象b的起始地址
    //  2.(int *)&b 强转成int *类型,为了后面取b对象的前四个字节,前四个字节是虚表指针
    //  3.*(int *)&b 取前四个字节,即vptr虚表地址
    //

    //  *****printf("第一个虚函数地址:%p\n", *(int *)*(int *)&b);*****:
    //  根据上面的解析我们知道*(int *)&b是vptr,即虚表指针.并且虚表是存放虚函数指针的
    //  所以虚表中每个元素(虚函数指针)在32位编译器下是4个字节,因此(int *)*(int *)&b
    //  这样强转后为了后面的取四个字节.所以*(int *)*(int *)&b就是虚表的第一个元素.
    //  即f()的地址.
    //  那么接下来的取第二个虚函数地址也就依次类推.  始终记着vptr指向的是一块内存,
    //  这块内存存放着虚函数地址,这块内存就是我们所说的虚表.
    //
    printf("虚表地址:%p\n", *(int *)&b);
    printf("第一个虚函数地址:%p\n", *(int *)*(int *)&b);
    printf("第二个虚函数地址:%p\n", *((int *)*(int *)(&b) + 1));

    Fun pfun = (Fun)*((int *)*(int *)(&b));  //vitural f();
    printf("f():%p\n", pfun);
    pfun();

    pfun = (Fun)(*((int *)*(int *)(&b) + 1));  //vitural g();
    printf("g():%p\n", pfun);
    pfun();

}

参考文献:

http://blog.csdn.net/haoel/article/details/1948051    (注:此文的取虚表地址代码有问题)

时间: 2024-10-14 02:22:31

获取C++虚表地址和虚函数地址的相关文章

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

讲解之前,了解下什么是虚函数,什么是虚表指针,了解下语法,(也算复习了) 开发知识为了不码字了,找了一篇介绍比较好的,这里我扣过来了,当然也可以看原博客链接: http://blog.csdn.net/hackbuteer1/article/details/7558868 一丶虚函数讲解(复习开发,熟悉内存模型) 1.复习开发知识 首先:强调一个概念 定义一个函数为虚函数,不代表函数为不被实现的函数. 定义他为虚函数是为了允许用基类的指针来调用子类的这个函数. 定义一个函数为纯虚函数,才代表函数

获取类中虚函数地址

// CMemory.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <IOSTREAM> using namespace std; class Base { public: virtual void f() { cout << "Base::f" << endl; } virtual void g

C++ 虚函数表解析(比较清楚,还可打印虚函数地址)

C++ 虚函数表解析 陈皓 http://blog.csdn.net/haoel 前言 C++中的虚函数的作用主要是实现了多态的机制.关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数.这种技术可以让父类的指针有“多种形态”,这是一种泛型技术.所谓泛型技术,说白了就是试图使用不变的代码来实现可变的算法.比如:模板技术,RTTI技术,虚函数技术,要么是试图做到在编译时决议,要么试图做到运行时决议. 关于虚函数的使用方法,我在这里不做过多的阐述.大家可以

在类有成员变量的场景下, 按照虚表原理, 模拟虚函数实现

前言 当类没有成员变量的情况下,   类首地址有4个字节的空间, 这里可以放我们模拟出来的虚表入口地址. 当类有成员变量的情况下, 类首地址就是成员变量,  所以, 为了模拟虚表实现, 需要在成员变量前, 再定义一个int型变量, 用来存放模拟的虚表入口地址. 现在还得不到虚析构函数的地址, 暂时按照非虚析构函数进行模拟. 这个实验是在C++中模拟的. 模拟虚函数实现的用途 在非OOP语言(C语言)中, 模拟类的实现, 可以实现虚函数的效果. 效果 工程下载点 编译环境: vc6sp6 + wi

C++学习 - 虚表,虚函数,虚函数表指针学习笔记

虚函数 虚函数就是用virtual来修饰的函数.虚函数是实现C++多态的基础. 虚表 每个类都会为自己类的虚函数创建一个表,来存放类内部的虚函数成员. 虚函数表指针 每个类在构造函数里面进行虚表和虚表指针的初始化. 下面看一段代码: // // main.cpp // VirtualTable // // Created by Alps on 15/4/14. // Copyright (c) 2015年 chen. All rights reserved. // #include <iostr

多态&amp;虚函数

(1).对象类型: a.静态类型:对象声明时的类型,编译的时候确定 b.动态类型:对象的类型是运行时才能确定的 class A {}; class B:public A {}; int main() { B* b; A* a=b;//a的静态类型是A*,动态类型(运行时)类型是B* return 0; } (2).多态 a.静态多态:函数重载.泛性编程 int Add(int a,int b) { return a+b; } float Add(float a,float b) { return

C++虚函数:虚指针、虚表、虚函数入口地址

测试程序: //test.c #include"stdio.h" #include"string.h" class GSVirtual { public: void gsv(char *src) { char buf[200]; strcpy(buf,src); vir2(); } virtual void vir1() { printf("vir1"); } virtual void vir2() { printf("vir2&quo

关于虚函数的那些事儿

一.虚函数定义 在某基类中声明为virtual 并在一个或多个派生类中被重新定义的成员函数,用法格式为: virtual 函数返回类型 函数名(参数表) {函数体}; 虚函数是C++语言实现运行时多态的唯一手段,通过指向派生类的基类指针或引用,访问派生类中同名覆盖成员函数. 举个例子: class A{ public:virtual void p() { cout << "A" << endl; } }; class B : public A { public:

虚函数多态的实现细节

之前老是被问到虚函数多态的事情.......有个模棱两可的印象,正好遇到这个帖子了,所以再学习学习 http://www.cnblogs.com/shouce/p/5453729.html 1.什么是虚函数 简单地说:那些被virtual关键字修饰的成员函数就是虚函数.其主要作用就是实现多态性. 多态性是面向对象的核心:它的主要的思想就是可以采用多种形式的能力,通过一个用户名字或者用户接口完成不同的实现.通常多态性被简单的描述为“一个接口,多个实现”.在C++里面具体的表现为通过基类指针访问派生