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

文章目录

结论

虚函数表指针是虚函数表所在位置的地址。虚函数表指针属于对象实例。因而通过new出来的对象的虚函数表指针位于堆,声名对象的虚函数表指针位于栈

虚函数表位于只读数据段(.rodata),即:C++内存模型中的常量区;

虚函数代码则位于代码段(.text),也就是C++内存模型中的代码区

验证

先创建一个有虚函数的类A

cpp 复制代码
class A
{
public:
	A(){};
	~A(){};
	virtual void vfun(){cout<<"vfun called!"<<endl;}
};

既然要知道虚函数表的位置,那么自然就需要找到虚函数表的地址。我们知道,对于类A这种简单的类,其对象内存布局的最开始四个字节就是一个虚函数表指针(32位编译器),而这个指针变量的值自然就是虚函数表的地址了,因此,第一步就是获取这个虚函数表指针来找到虚函数表的地址

cpp 复制代码
A *a = new A();

long vbaddr=*(int *)a;   //虚函数表地址

由于只有一个虚函数,所以虚函数表的前4个字节肯定就是vfun的函数地址,因此根据虚函数表的地址还可以得到虚函数vfun的地址:

cpp 复制代码
long vfaddr= *(int *)vbaddr;  //虚函数A::vfun的地址

然后还可以根据vfun的地址来调用这个函数:

cpp 复制代码
((void(*)(void))vfaddr)();  //根据得到的地址来调用虚函数 

如果通过vfaddr来调用函数是成功的,那么就说明前面虚函数表的地址都是正确的。

完整程序:

cpp 复制代码
#include <iostream>
#include <stdio.h>
using namespace std;
 
class A
{
public:
	A(){};
	~A(){};
	virtual void vfun(){cout<<"vfun called!"<<endl;}
};
 
int main()
{
	A *a = new A();
	long vbaddr=*(int *)a;   //虚函数表地址
	long vfaddr= *(int *)vbaddr;   //虚函数vfun地址
    printf("addr of vb: %x\n", vbaddr);
    printf("addr of vfun: %x\n", vfaddr);

	// cout<<"addr of vb : "<<vbaddr<<endl;
	// cout<<"addr of vfun : "<<vfaddr<<endl;
	
	((void(*)(void))vfaddr)();   //根据虚函数地址调用虚函数
 
	delete a;
	return 0;
}

用g++进行编译生成可执行文件,然后运行:

从运行结果可以看到,虚函数表的地址是0x400b40,虚函数vfun的地址为0x400a3c,并且根据虚函数vfun的地址成功调用了虚函数,打印了"vfun called!",这说明获取的0x400b40确实是虚函数表的地址

接下来就看看0x400b40这个地址在可执行文件内存中的哪个段

objdump -s可以解析ELF格式的可执行文件中的分段信息:

每个分段的内容用Contents of section .xxx来分隔,xxx表示下面的内容属于哪个段。在这些段的内容中,每一行的第一个16进制数表示的是相应的段中的一个地址,以400274 04000000 140...这一行为例,首地址为0x400274,那么从0x400274到下一行首地址0x400284之间的16个字节中存放的数据就是0x04000000 14000000 030...

回到虚函数表的地址上来,前面说了,虚函数表的地址为0x400b40,现在来看看这个地址是属于哪个段:

可以看到,0x400b40这个地址,刚好就在.rodata这个段中,这个段就是C++中的常量区,并且还可以发现,从这个地址开始取4个字节"3c0a4000",由于是小端模式,因此取出来的4字节数为0x400a3c,是不是很眼熟呢?没错,这个地址就是前面求得的虚函数vfun的地址。

同理,根据虚函数vfun的0x400a3c地址,还可以找到虚函数vfun的位置:

可以看到,虚函数vfun位于.text代码段

综上所述: C++中虚函数表位于只读数据段(.rodata),也就是C++内存模型中的常量区;而虚函数则位于代码段(.text),也就是C++内存模型中的代码区。

相关推荐
Trouvaille ~25 天前
【C++篇】虚境探微:多态的流动诗篇,解锁动态的艺术密码
c++·面试·性能优化·多态·面向对象编程·代码优化·虚函数
BLR.cpp3 个月前
c++如何理解多态与虚函数
多态·虚函数·c++虚函数·c++多态·编译时多态·运行时多态·父类指针调用虚函数
一只特立独行的猪( ﹡ˆoˆ﹡5 个月前
虚函数机制-动态绑定的应用
虚函数
阮春义6 个月前
C++ Virtual Functions
虚函数·polymorphic class
GOTXX8 个月前
C++多态
开发语言·c++·多态·虚函数表·多态原理·final关键字·单继承,多继承虚函数表
菠菠萝宝8 个月前
C++程序设计-第六/七/八章 运算符重载/包含与继承/虚函数和多态性【期末复习|考研复习】
开发语言·c++·考研·继承·期末复习·虚函数·重载
丶布布1 年前
[C++从入门到精通] 14.虚函数、纯虚函数和虚析构(virtual)
开发语言·c++·虚函数·纯虚函数·虚析构
郑同学的笔记1 年前
【c++随笔14】虚函数表
开发语言·c++·虚函数表
郑同学的笔记1 年前
【c++随笔13】多态
开发语言·c++·多态·虚函数表