C++ 内存划分与虚函数表在内存中的位置
2015-09-05 22:28
274 查看
一直都不清楚C++的内存具体是怎样划分的,只知道大致有堆区、栈区、全局静态区、常量区等划分。如果没记错的话,好像还有一个代码区。
现在的问题是,C++里的虚函数是借助虚函数表实现的,含有虚函数的类的对象中有一个指向虚函数的指针(通常是对象前4个字节(32位))。
那么,虚函数表是保存在内存中的哪个部分中呢?
在网上查了一些资料也没搞明白,只好自己动手研究。
首先进行简单的分析,虚函数表应该是在编译期就已经决定了的,所以不可能在堆区与栈区。虚函数也不属于代码,所以推测在静态区或常量区。
有一个简单的测试思路,写一个简单的C++程序,把各个区段的地址和虚函数表地址都输出出来,通过地址的位置来判断。
撸出代码如下:
运行后输出结果:
sizeof(void*) 4
〇〇〇栈区:0x0029FEE4
〇〇〇栈区:0x0029FEE0
〇〇〇栈区:0x0029FE7C
〇〇函数区:0x00401334
〇〇常量区:0x0040E04E
〇〇常量区:0x0040E055
〇〇常量区:0x0040E0D0
〇虚函数表:0x0040FCD0
〇虚函数表:0x0040FCE8
全局静态区:0x00411014
全局静态区:0x00411018
〇〇〇堆区:0x00830DF0
〇〇〇堆区:0x00830E60
推测出内存划分为以下几个部分:
栈区
函数区(函数区是代码区吗?)
常量区
虚函数表(虚函数表属于哪个区段?)
全局静态区
堆区
因此,虚函数表介于常量区和全局区之间。虚函数表似乎可以单独作为一个分区,或许内存划分方式并不像想象中那么严格。
以后查到资料再回来添加。
现在的问题是,C++里的虚函数是借助虚函数表实现的,含有虚函数的类的对象中有一个指向虚函数的指针(通常是对象前4个字节(32位))。
那么,虚函数表是保存在内存中的哪个部分中呢?
在网上查了一些资料也没搞明白,只好自己动手研究。
首先进行简单的分析,虚函数表应该是在编译期就已经决定了的,所以不可能在堆区与栈区。虚函数也不属于代码,所以推测在静态区或常量区。
有一个简单的测试思路,写一个简单的C++程序,把各个区段的地址和虚函数表地址都输出出来,通过地址的位置来判断。
撸出代码如下:
#include <cstdio> #include <cstdlib> using namespace std; typedef void (*FP)(); FP fp; void fun() { int t; printf("〇〇〇栈区:0x%08X\n", (unsigned)&t); } class Base { public: virtual void gao() { printf("Base\n"); } virtual ~Base() {} }; class Derived : Base { public: virtual void gao() { printf("Derived\n"); } virtual void dio() { printf("URYYYYYY\n"); } virtual ~Derived() {} }; Base b; Derived d; int glob = 0; int glob2 = 0; const int cons = 0; int main() { int stk = 0; int stk2 = 0; const char *p = "123456"; const char *p2 = "3333"; unsigned table = *((unsigned*)&b); unsigned table2 = *((unsigned*)&d); printf("sizeof(void*) %d\n", sizeof(void*)); char *heap =(char *) malloc(100); char *heap2 = new char[100]; printf("〇〇〇栈区:0x%08X\n", (unsigned)&stk); printf("〇〇〇栈区:0x%08X\n", (unsigned)&stk2); fun(); fp = fun; printf("〇〇函数区:0x%08X\n", (unsigned)&(*fp)); printf("〇〇常量区:0x%08X\n", (unsigned)&(*p)); printf("〇〇常量区:0x%08X\n", (unsigned)&(*p2)); printf("〇〇常量区:0x%08X\n", (unsigned)&cons); printf("〇虚函数表:0x%08X\n", table); printf("〇虚函数表:0x%08X\n", table2); printf("全局静态区:0x%08X\n", (unsigned)&glob); printf("全局静态区:0x%08X\n", (unsigned)&glob2); printf("〇〇〇堆区:0x%08X\n", (unsigned)&(*heap)); printf("〇〇〇堆区:0x%08X\n", (unsigned)&(*heap2)); return 0; }
运行后输出结果:
sizeof(void*) 4
〇〇〇栈区:0x0029FEE4
〇〇〇栈区:0x0029FEE0
〇〇〇栈区:0x0029FE7C
〇〇函数区:0x00401334
〇〇常量区:0x0040E04E
〇〇常量区:0x0040E055
〇〇常量区:0x0040E0D0
〇虚函数表:0x0040FCD0
〇虚函数表:0x0040FCE8
全局静态区:0x00411014
全局静态区:0x00411018
〇〇〇堆区:0x00830DF0
〇〇〇堆区:0x00830E60
推测出内存划分为以下几个部分:
栈区
函数区(函数区是代码区吗?)
常量区
虚函数表(虚函数表属于哪个区段?)
全局静态区
堆区
因此,虚函数表介于常量区和全局区之间。虚函数表似乎可以单独作为一个分区,或许内存划分方式并不像想象中那么严格。
以后查到资料再回来添加。
相关文章推荐
- 为什么用了#ifndef还说我重复定义?
- 关于C++中父类指针引用对象在内存中的分布
- c语言学习第二天
- 最值得你所关注的10个C语言开源项目(转自红联)
- C++_运算符重载
- C/C++中的static使用
- c语言基础学习记录第一天
- C++/CLI——读书笔记《Visual C++/CLI从入门到精通》 第Ⅳ部分
- c++的深拷贝和浅拷贝
- C++的抽象类理解
- 提高C++程序运行效率的10个简单方法
- c++primer之顺序容器(访问元素)
- C/C++ struct/class/union内存对齐 [转]
- const在c++中的用法分析
- C++技术点积累(1)
- 【C++】嵌套类、友元
- 在C#中使用C++编写的类
- c语言学习之顺序结构
- C/C++笔试题目大全
- 编辑距离