对象内存布局(MSVC2017)
来源:互联网 发布:windows安装centos引导 编辑:程序博客网 时间:2024/06/06 20:08
对象内存布局(MSVC2017)
本文主要介绍c++对象在内存中的分布
class B 直接继承于 class A
class A{public: A() { m_A = 1; } virtual ~A() {} virtual void fun1() {}public: int m_A;};class B : public A{public: B() { m_B = 2; } virtual ~B() {} virtual void fun1() {} virtual void fun2() {}public: int m_B;};
内存结构:
+0x00
指向B的虚表指针
+0x04
基类A的成员m_A
+0x08
B的成员m_B
B的虚表中存放B的虚函数地址
class B 虚继承于 class A
class A{public: A() { m_A = 1; } virtual ~A() {} virtual void fun1() {}public: int m_A;};class B : virtual public A{public: B() { m_B = 2; } virtual ~B() {} virtual void fun2() {}public: int m_B;};
内存结构:
+0x00
指向B的虚表指针
+0x04
指向偏移表的指针
+0x08
B的成员m_B
+0x0C
虚基类A的虚表指针
+0x10
虚基类A的成员m_A偏移表第一项为自身的偏移
-4
第二项为虚基类A的偏移8
偏移0位置为偏移表指针所在位置
B的虚表中存放B的虚函数地址
A的虚表中存放B继承的的虚函数地址
class B 虚继承于 class A 且覆盖A的虚函数
class A{public: A() { m_A = 1; } virtual ~A() {} virtual void fun1() {}public: int m_A;};class B : virtual public A{public: B() { m_B = 2; } virtual ~B() {} virtual void fun1() {} virtual void fun2() {}public: int m_B;};
会在虚基类前添加一个全0标志
class C 继承于 class A 和 class B
class A{public: A() { m_A = 1; } virtual ~A() {} virtual void fun1() {}public: int m_A;};class B{public: B() { m_B = 2; } virtual ~B() {} virtual void fun2() {}public: int m_B;};class C : public A, public B{public: C() { m_C = 3; } virtual ~C() {} virtual void fun3() {}public: int m_C;};
内存结构:
+0x00
指向A的虚表的指针
+0x04
A的成员m_A
+0x08
指向B的虚表的指针
+0x0C
B的成员m_B
+0x10
C的成员m_C
其中C的虚函数地址存放在A的虚表之后,与A的虚表合并
class C 虚继承于 class A 和 class B
class A{public: A() { m_A = 1; } virtual ~A() {} virtual void fun1() {}public: int m_A;};class B{public: B() { m_B = 2; } virtual ~B() {} virtual void fun2() {}public: int m_B;};class C : virtual public A, virtual public B{public: C() { m_C = 3; } virtual ~C() {} virtual void fun3() {}public: int m_C;};
内存结构:
+0x00
指向C的虚表的指针
+0x04
指向偏移表的指针
+0x08
C的成员m_C
+0x0C
虚基类A的虚表指针
+0x10
虚基类的成员m_A
+0x14
虚基类B的虚表指针
+0x18
虚基类B的成员m_B其余与单继承相同
)
class C、class B继承于 class A,class D 继承于class C、class B(菱形继承)
class A{public: A() { m_A = 1; } virtual ~A() {} virtual void fun1() {}public: int m_A;};class B : public A{public: B() { m_B = 2; } virtual ~B() {} virtual void fun2() {}public: int m_B;};class C : public A{public: C() { m_C = 3; } virtual ~C() {} virtual void fun3() {}public: int m_C;};class D : public B, public C{public: D() { m_D = 4; } virtual ~D() {} virtual void fun4() {}public: int m_D;};
内存结构:
+0x00
指向A的虚表的指针其中存放A,B,D的虚函数地址
+0x04
A的成员m_A
+0x08
B的成员m_B
+0x0C
指向A的虚表的指针
其中存放A,C的虚函数地址
+0x10
A的成员m_A
+0x14
C的成员m_C
+0x18
D的成员m_D
class C、class B虚继承于 class A,class D 虚继承于class C、class B(菱形虚继承)
class A{public: A() { m_A = 1; } virtual ~A() {} virtual void fun1() {}public: int m_A;};class B : virtual public A{public: B() { m_B = 2; } virtual ~B() {} virtual void fun2() {}public: int m_B;};class C : virtual public A{public: C() { m_C = 3; } virtual ~C() {} virtual void fun3() {}public: int m_C;};class D : virtual public B, virtual public C{public: D() { m_D = 3; } virtual ~D() {} virtual void fun4() {}public: int m_D;};
内存结构:
+0x00
指向D的虚表的指针
+0x04
指向D的偏移表的指针
+0x08
D的成员m_D
+0x0C
虚基类A的虚表指针
+0x10
虚基类的成员m_A
+0x14
虚基类B的虚表指针
+0x18
虚基类B的偏移表指针
+0x1C
虚基类B的成员m_B
+0x20
虚基类C的虚表指针
+0x18
虚基类C的偏移表指针
+0x1C
虚基类C的成员m_C
总结一下
派生类成员在基类成员之后,在虚基类成员之前。
在基类有虚函数的时候,会在该基类及每个该基类的派生类生成一个虚表指针,虚表指针为该类的首个成员,虚表指针指向该类的虚函数地址数组。
在虚继承时,同时还会在派生类生成一个偏移表指针(指向偏移表,用于定位虚基类位置),偏移表第一项为自身偏移,第一项为第一个虚基类的偏移,第二项为第二个虚基类的偏移,偏移表的值于偏移表指针相加即可得到自己或父类的内存地址。
- 对象内存布局(MSVC2017)
- c++对象内存模型(内存布局)
- C++对象的内存布局(上)
- C++对象的内存布局(下)
- C++ 对象的内存布局(上)
- C++ 对象的内存布局(下)
- C++ 对象的内存布局(上)
- C++ 对象的内存布局(中)
- C++ 对象的内存布局(下)
- C++ 对象的内存布局(上)
- C++ 对象的内存布局(下)
- C++ 对象的内存布局(下)
- C++ 对象的内存布局(上)
- C++ 对象的内存布局(上)
- C++ 对象的内存布局(上) .
- C++ 对象的内存布局(下) .
- C++ 对象的内存布局(上)
- C++ 对象的内存布局(下)
- [java多线程]如何安全的退出线程
- c/c++可执行程序的生成过程
- java定时任务,每天定时执行任务
- Regular Expression Matching
- [笔记]char* 转 unsigned char*
- 对象内存布局(MSVC2017)
- haxe 第一期 入门骗 (谷歌翻译+转载)
- Oracle给账户解锁
- Codeforces 235C Cyclical Quest 后缀自动机
- Python安装
- Xcode中描述文件的真实目录
- 【Java编程思想笔记】第一章——对象导论
- js 数据类型处理
- 171019 逆向-Reversing.kr(MetroApp)