两种获取虚函数地址的方式

C++知识积累:如何获取虚函数表以及虚函数地址 如果一个类中存在虚函数的话,那么编译器就会为这个类生成一个虚函数表,这个虚函数表中按照个虚函数的声明顺序存放了各个虚函数的地址,需要注意的是,这个虚函数表并不存在于类中,而对于这个类的每个对象,编译器都会为其生成一个透明不可见的指针,这个指针就是虚函数表指针,位于该对象内存中的开头,并指向了虚函数表的位置。换句话说,如果一个类中存在虚函数,假设声明一个对象a,在32位的编译情况下,对... 阅读详情

今天在运行一段代码时,发现运行结果与我预期的不一样,所以google了一把,这里对研究结果作下总结

#pragma once
#include <iostream>
using std::cout;
using std::endl;
class Base
{
public:
	virtual void f()
	{
		cout<<"Base f"<<endl;
	}

	virtual void g()
	{
		cout<<"Base g"<<endl;
	}
};

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

class Der2 : public Base
{
public:
	void f()
	{
		cout<<"Der2 f"<<endl;
	}

	void g()
	{
		cout<<"Der2 g"<<endl;
	}
};
#include "test.h"

typedef void (Base::*fbase)();
typedef void (Der1::*fdera)();
typedef void (Der2::*fderb)();
//typedef	void (Base::*g)();
//typedef void (*func)();
int main()
{
	//Base* pbase = new Base;

	//printf("instance addr = %p\n", pbase);

	//f fbase= &Base::f;
	//printf("Base::f addr = %p\n", fbase);

	//g gbase= &Base::g;
	//printf("Base::g addr = %p\n", gbase);

	//func pf = (func)(*(int*)*(int*)(pbase));
	//printf("f addr = %p\n", pf);
	//pf();
	//pf = (func)*((int*)*(int*)(pbase) + 1);
	//printf("g addr = %p\n", pf);
	//pf();
	fbase f1 = &Base::f;
	printf("Base::f addr = %p\n", f1);

	fdera f2 = &Der1::f;
	printf("Der1::f addr = %p\n", f2);

	fderb f3 = &Der2::f;
	printf("Der2::f addr = %p\n", f3);

	return 0;
}


Der1和Der2是Base的派生类,并且两个类都重写了基类的两个虚函数f和g。对于main函数,我最初期望输出的是三个不同的指针值,但是运行结果输出了一样的值,运行结果如下:

 在这里输出运行结果

结果出乎意料,于是搜了2篇帖子进行研究:

1、VC虚函数布局引发的问题 http://blog.youkuaiyun.com/zhanglei8893/article/details/6333751

2、C++虚函数表学习心得之由类实例地址到虚函数表再到虚函数地址中各种地址解析http://blog.youkuaiyun.com/chenqin158741019/article/details/8074945?reload

第一篇介绍了访问虚表的两种方式,一种是通过类对象实例地址转化来访问,另一种是通过vcall thunk技术;第二篇具体介绍了如何通过类对象实例访问虚表。

通过阅读这两篇文章,我对vcall thunk技术有了初步的概念。main函数中输出的3个地址值都对应一个调用Base::`vcall'{0}' (0表示虚函数表中第1个函数),所以这三个值并非真正的虚函数地址,真正的地址在vcall调用中计算,vcall的反汇编代码为:

00411082  mov         eax,dword ptr [ecx] 
00411084 jmp         dword ptr [eax]  
//我没有进行过反汇编,两条指令的地址值是根据我自己运行的结果更改的

ecx寄存器中保存着this指针,所以vcall是以this指针为基础,通过跳转偏移this指针若干个单位来寻找相应的虚函数地址(如第2个虚函数,jmp指令参数就变为dword ptr [eax+4],该指令的意思是调转到偏移this指针4字节的位置的那个双字指针指向的指令执行,不知道解释对不对,要去复习下汇编)。至于为什么可以这样查找,是因为虚函数表指针存放在类对象的开始位置,每个虚函数指针的大小又固定,所以只要知道要找的虚函数地址位于虚函数表的第几个slot(按照在类中的声明顺序),就能计算出虚函数地址。 

       虽然main函数中派生类的成员函数指针与基类值一样,但那并不是真正虚函数指针的值。在vcall中计算得到的值才是真正虚函数指针的值。

 

注:不知道我的有些理解是不是准确,但目前这样理解有助于我记忆,或许以后我有更深的理解

 


 

打印虚函数的地址(C++) #pragma once #include<iostream> //Base是基类 //Derive是Base的派生类 //两者里面的函数我都用了虚函数 //我们来看Derive,其中的func1是重写了Base::func1;3/4是他自己的 //然后我们现在来通过自定义函数来查看下虚表里,各个虚函数的地址-------PrintfVTable //接下来的注释转到PrintVTable namespace qcb{ class Base{ public: virtual void f 阅读详情

相关推荐

虚函数表获取的函数地址和函数实际地址一样吗?

 最近,看帖发现不少人对虚函数表很迷惑,说虚函数表中函数的地址怎么和用函数指针获取的地址不一致?示例代码如下:#include #include using namespace std; class Base { public: virtual void f() { cout

Mike的专栏 6278

C++ 获取类成员虚函数地址

1.GCC平台GCC平台获取C++成员虚函数地址可使用如下方法[1]^{[1]}:class Base{ int i; public: virtual void f1(){ cout&lt;&lt;&quot;Base's f1()&quot;&lt;&lt;endl; } };Base b; void (Base::*mfp)() = &amp;Base::f1; printf(&quo

Doublelv 的博客专栏。 2775

C++虚函数表学习心得之由类实例地址到虚函数表再到虚函数地址中各种地址解析

C++虚函数是继承多态的核心,常规语法相信很多朋友都很熟悉了,这里有一篇牛人关于C++虚函数表很好的博客:http://blog.youkuaiyun.com/haoel/article/details/1948051/ 我这里只是在此基础上谈谈各种地址与指针转换的心得。          大家都知道虚函数表在内存中存在的地址位于类实例首地址中,楼主这里的编程环境是WIn7 64bit,VS2010,废话

轩雨阁 4156

c++虚函数地址的获取

最近在做的一个项目的一个步骤找到虚函数的实际地址。这个过程中遇到的问题,让我感觉到了自己对于C++指针的理解还是不够透彻,记录一下。 概念 指针由两个空间组成 一是指针本身占有一定的空间,32位操作系统下是4byte 32bit,64位操作系统下是8byte 64bit。 二是这个占有的空间中存放一个地址,这个地址代表另一个空间,这个空间所占的大小信息由指针的类型表示。 指针赋值 直接=...

h_Rhin0的博客 1414

如何获取C++类成员虚函数地址的示例代码

主要给大家介绍了关于C++如何获取类成员虚函数地址的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面跟着小编来一起学习学习吧。

中国高质量夜间灯光数据

中国高质量夜间灯光数据是CnOpenData与吉林高分遥感应用研究院有限公司合作的数据库 ,基于多源夜间灯光卫星遥感影像,经过科学手段对数据进行降噪、修正、分析统计,以年度、月度为更新频率,以省市县三级行政区划作为统计单元,制作高质量夜间灯光数据。

Sunny9qx的博客 3310

C/C++ 获取函数地址

C C语言中没有类的概念,只有普通的函数。通过函数名就可以得到函数地址 #include <stdio.h> #include <stdlib.h> void fun() { } int main() { printf("%p\n", &fun); } 对于 fun 和 &fun 应该这样理解: fun 是函数的首地址,它的类型是 void () &fun 表示一个指向函数 fun 这个对象的地址, 它的类型是 void (*)() 因此 fun 和

lhh_qrsly的博客 8105

手把手调试:如何为高通Hypervisor上的GuestOS添加一个自定义的HAB服务通道

本文详细介绍了如何在高通Hypervisor环境下为GuestOS添加自定义HAB服务通道的全过程。从HAB通信框架的核心概念解析到设备树节点的动态注入机制,再到物理通道的内核层实现和用户层测试,提供了完整的开发案例和调试技巧,帮助开发者高效构建定制化通信服务。

weixin_27066963的博客 371

【C/C++】概念: VC虚函数布局引发的问题

在网上看到一个非常热的帖子,里面是这样的一个问题:      在打印的时候发现pFun的地址和 &(Base::f)的地址竟然不一样太奇怪了?经过一番深入研究,终于把这个问题弄明白了。下面就来一步步进行剖析。       根据VC的虚函数的布局机制,上述的布局如下:  然后我们再细细的分析第一种方式:          Fun pFun = (F

晚晴小筑 1387

阿里云大模型ACP认证模拟考试(二)

摘要:在阿里云大模型高级工程师 ACP 认证暂无真题题库的现状下,模拟题具有重要意义。其依照真实考试设计,涵盖题型、题量与分值分布,助力考生熟悉考试框架,合理分配答题时间精力,提升效率。同时,模拟题紧扣官方课程,能帮助考生精准定位知识盲点,如大模型架构原理和通义千问应用实践等重点内容,以便针对性完善知识体系。此外,通过练习模拟题,考生可掌握不同题型的解题思维与技巧,快速洞察复杂题目本质,提高答题准确率。

davidkorhenn的博客 2076

complier lab2

只需支持定义 main 函数即可不带参数 int main(){...}带参数 int main(int argc, int argv){...}

qq_43581843的博客 906

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

获取C++虚表地址和虚函数地址                                By qianghaohao        学过C++的应该都对虚表有所耳闻,在此就不过多介绍概念了,通过实例来 演示一下如何获取虚表地址和虚函数地址。          简单说一下虚表的概念:在一个类中如果有虚函数,那么此类的实例中就有 一个虚表指针指向虚表,这个虚表是一块儿专门存放类的虚

qhh0205 1万+

从零到一:Silvaco中跨导曲线的自动化脚本实现

本文详细介绍了如何使用Python脚本在Silvaco中实现跨导曲线(gm曲线)的自动化分析,包括数据加载、跨导计算和结果可视化。通过自动化处理Id-Vg曲线,显著提升半导体器件工程师的工作效率,特别适用于工艺优化和DOE分析。文章还提供了批量处理和关键参数提取的高级技巧,帮助工程师快速掌握Silvaco脚本开发。

nn3456的博客 567

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

学过C++的应该都对虚表有所耳闻,在此就不过多介绍概念了,通过实 例来演示一下如何获取虚表地址和虚函数地址。         简单说一下虚表的概念:在一个类中如果有虚函数,那么此类的实例中就有一个虚表指针指向虚表,这个虚表是一块儿专门存放类的虚函数地址的内存。        图示说明本文的主题(先看图更容易后面代码中的指针操作):               代码如下(要讲解的都在代码的注释中说明...

小郑的博客 9238

【2022网易雷火】游戏研发笔试-AC代码及题目分享

3个小时,4道题目,雷火的题目不在于难,更在于对细节的把控和写大模拟的耐心,花了一个半小时,AC了3.85,直接交卷退了。第一题AC,第二题AC,第三题85%,第四题AC。下面分享一下大致的题意和对应的代码,就不多说了,最近很累(代码可能会有贴错的情况,如有望指正,感谢~)。 T1-小Y抽奖 题意 n行m列个奖励格子,每次抽奖消耗一个道具。每个格子奖励的数量有限且各不相司。每个格子被抽到一次,剩余的奖励数量-1。剩余的奖励数量为0时,则不会再抽到该格子。小Y抽了好多次,但一直没有抽到最想要的..

米莱虾 9266

实战交易策略 篇二十二:情绪流龙头交易策略

在股票市场中,机构主导趋势,游资驱动热点,散户易被情绪裹挟,形成“金字塔”式生态链,并存在情绪传递、强者恒强、物极必反的规律特点。股市是资金驱动的情绪博弈场,价格波动由群体心理、资金博弈和预期差共同驱动,核心是资本逐利性与人性贪婪恐惧的交织,兼具资源配置、财富再分配与风险定价功能。涨停加速与逃逸缺口(主升强化)凹字板/平台突破(趋势延续)天量弱转强(分歧买点)不参与首波(二波策略)情绪周期(道术合一)主线思维(聚焦核心)开盘抢筹(竞价博弈)一字助攻(情绪强化)分批进出(滚动操作)

生活在别处 1499

C++中如何获取虚表和虚函数的地址

funcB_addr2:将vtable_addr + sizeof(intptr_t),先强转为指向虚函数地址的指针,再解引用,即得到第二个虚函数的地址,对于32位系统sizeof(intptr_t)的值为4,64位系统则等于8。funcB_addr就类似p1,funcB_addr2类似于p1_2,virtual_func_ptr类似于p,vtable_addr类似于addr,虚函数地址即为元素,每个元素占sizeof(intptr_t)个字节。本文主要讨论如何获取。

Black.Spider的博客 1214

092、多sensor帧同步在环视系统中的实现——基于瑞芯微RK3588的PPS同步与曝光同步方案

摘要: 本文探讨了瑞芯微RK3588平台在360环视系统中实现多摄像头帧同步的技术方案。针对环视拼接常见的动态场景错位问题,提出了PPS同步与曝光同步相结合的解决方案。通过GPIO硬件触发实现四路摄像头同步曝光,配合I2C全局曝光控制,将时间误差控制在0.5ms内。文章详细解析了RK3588设备树配置、内核驱动实现中的关键细节,包括同步信号处理、寄存器原子写入等核心技术点,并分享了量产中遇到的温度漂移、信号完整性等实际问题及解决方法。最终通过硬件整形和电源优化,将同步抖动控制在±5μs以内,有效解决了动态拼

zzfmlxs的博客 33

虚函数表构成、地址详细说明

以下代码都是小弟自己敲的,图也是自己画的 厚颜看完之后如果有用给个顶一下 一.什么是虚函数表,它有什么特点? 虚函数大家都知道是基本用于实现多态的,当父类指针指向子类对象的时候,如何确定调用的函数是父类里的还是子类里面的,这就要用到虚函数表。下面一点点表诉什么是虚函数表,和虚函数表的特点。如有说错的地方,欢迎指正: 1.编译器会为每个有虚函数的类创建一个虚函数表 如有类中没有虚函数,那么这个虚函...

专注音视频底层算法与工程实现,深入解析数字信号处理。深入研究WebRTC 3A、多麦声源定位、vad、语音识别等技术 2689

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

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

C++虚表地址和虚函数地址 虚函数是c++实现多态性的一个重要知识点,本文主要解析虚函数在内存中的地址,以及与虚表地址的关系。 声明一个类,包含两个虚函数,一个普通成员函数和一个类成员。 调试程序,查看test对象的内存分布如下: _vptr是一个指向虚表的指针,可以理解为一个int* p[2],在本例中,p[0]是指向Test::func1()地址的指针,p[1]是指向Test::func2...

bajianxiaofendui的博客 8764

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

C++虚函数表地址偏移

#include <bits/stdc++.h> using namespace std; class Base { public: Base() { cout << "Base构造" << endl; } virtual ~Base() { cout << "Base虚析构" << endl; } virtual void f1() { cout << "Base::f1()" << endl;

NIRVANA REBIRTH 1469

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

虚函数表地址,虚函数地址,虚函数指针的地址

虚函数表地址,虚函数地址,虚函数指针的地址

xiao_ZHEDA的博客 1044

C++ 虚函数详解

文章目录虚函数的作用虚函数的原理:虚函数表指针和虚函数表虚函数表存储虚函数的顺序析构函数和虚函数纯虚函数 虚函数的作用 虚函数是为了实现动态多态。多态是指为不同的数据类型提供统一的接口,分为静态多态和动态多态。静态多态包括函数重载和模板函数,动态多态是:指针或引用类型可以根据运行中实际指向的派生类型的不同,来执行不同派生类的方法。 举个例子,有一个基类 Character 表示职业统称,玩家会选择职业战士 Warrior 或者魔法师 Magician,然后所有的逻辑例如攻击,防守都会根据玩家选择的不同职业有

竹剑单 9574

C++获取虚表地址和虚函数地址时的两个强制类型转换

今天学习虚函数时看到代码中的两个强制类型转换十分不解,查了蛮多资料,终于知道了原因,因此写下自己的见解。 简单说一下虚表的概念:在一个类中如果有虚函数,那么此类的实例中就有一个虚表指针指向虚表,这个虚表是一块儿专门存放类的虚函数地址的内存。 通过sizeof运算符我们可以查看一个对象所占的空间,对于一个只有函数(无虚函数)没有属性的空类对象,它的空间长度为1,而对于有虚函数、没有属性的空类对象...

yangwenxiao123456的博客 1148

虚函数表和虚函数在内存中的位置

虚函数表和虚函数在内存中的位置

冯同学的博客 2830

如何获取虚函数表指针?虚函数表地址?虚函数地址?

如何获取虚函数表指针?虚函数表地址?虚函数地址?

qq_53398102的博客 973
上一篇: C++ 随机数生成
下一篇: 逆序存储小文件(一)——使用STL容器
sunchenxian017
博客等级 码龄16年 2粉丝 13原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值