c++底层剖析(1)
来源:互联网 发布:java socket 即时通讯 编辑:程序博客网 时间:2024/05/29 17:34
首先从带有虚函数的基类派生讲起。
class Base{public:Base(){base = 1; cout<<"Base!\n";}virtual ~Base(){cout<<"~Base!\n";}virtual void say(){cout<<"hello Base\n";}int base;};class Derive : public Base{public:Derive(){derive = 2;}virtual ~Derive(){cout<<"~Derive!\n";}virtual void say(){cout<<"hello Derive\n";}int derive;};int _tmain(int argc, _TCHAR* argv[]){Base *pd=new Derive;pd->say();delete pd;return 0;}这是一个很简单的派生的例子,首先从内存角度看下,期中0x003B94B0为指针pd的值
可以看到最开始的四个字节的值为0x00417700, 后面是两个int型值分别为1和2,代表着base和derive的值,这两个值是在构造函数里进行赋值的,现在主要看下0x00417700这个值代表着什么?
0x00417700这个内存位置的值是0x004112c6,在继续跟下0x004112c6这个内存位置有什么东西
004112C6 jmp Derive::`scalar deleting destructor' (414980h)
可以看到这个地方是跳到一个好像是Derive的析构函数处,其实进去之后会发现其实他是一个代理函数,在此函数中先调用Derive的析构函数,然后在调用operator delete 释放内存。可以通过反汇编代码来看下:
Derive::`scalar deleting destructor':
00414980 push ebp
。。。。
0041499F pop ecx
004149A0 mov dword ptr [ebp-8],ecx
004149A3 mov ecx,dword ptr [this]
004149A6 call Derive::~Derive (4112B2h)
004149AB mov eax,dword ptr [ebp+8]
004149AE and eax,1
004149B1 je Derive::`scalar deleting destructor'+3Fh (4149BFh)
004149B3 mov eax,dword ptr [this]
004149B6 push eax
004149B7 call operator delete (4110D2h)
中间的省略掉了,无关紧要,主要是将开辟的一段栈空间的内容初始化为0xcccccccc,在红色处可以看到Derive的析构函数的调用。现在在回到开头处,用一张图示意下
可以看到Derive类型的对象的内存布局,首先是一个虚表指针,然后是基类的成员变量最后才是自己的成员变量
现在来观看下这个指向虚表的指针式什么时候安插到对象的头部的,我们通过派生类的构造函数来看下:
Derive()
004116A0 push ebp
。。。。。。
004116BF pop ecx
004116C0 mov dword ptr [ebp-8],ecx //ecx为this的值
004116C3 mov ecx,dword ptr [this]
004116C6 call Base::Base (41115Eh)
004116CB mov eax,dword ptr [this]
004116CE mov dword ptr [eax],offset Derive::`vftable' (417700h)
通过观看构造函数的反汇编代码可以看到,在派生类的构造函数中先是调用基类Base的构造函数,现在我们跟到基类的构造函数中去:
Base():
004117B0 push ebp
。。。。。
004117CF pop ecx
004117D0 mov dword ptr [ebp-8],ecx
004117D3 mov eax,dword ptr [this]
004117D6 mov dword ptr [eax],offset Base::`vftable' (417718h)
004117DC mov eax,dword ptr [this]
004117DF mov dword ptr [eax+4],1
004117E6 push offset string "Base!\n" (417708h)
004117EB mov eax,dword ptr [__imp_std::cout (41B328h)]
004117F0 push eax
004117F1 call std::operator<<<std::char_traits<char> > (4111A4h)
通过基类的构造函数可以看到,他将offset Base::`vftable' (417718h)基类的虚表地址赋给了对象的头四个字节,然后才是执行基类构造函数中的代码,现在我们可以看到pd头部的四个字节的值不是417700h而是417718h,奇怪了别急,后面会看到417700h这个值是赋给pd头部的四个字节。基类的构造函数执行完毕之后回到派生类的构造函数,此事可以看到紧接着就是两个赋值语句
004116CB mov eax,dword ptr [this]
004116CE mov dword ptr [eax],offset Derive::`vftable' (417700h)
首先是将this指针的值赋给eax,然后将offset Derive::`vftable' (417700h)派生类的虚表的指针赋给eax所指向的地址的头四个字节,也就是赋给pd所指的派生类对象的头四个字节,现在到此也就分析完了其内存布局,以及虚表指针的赋值过程。
- c++底层剖析(1)
- ARM代码底层剖析——机器码,汇编,C
- linux设备驱动模型大剖析(1)-----底层阶级的程序猿
- C语言深度剖析笔记(1)
- static 剖析(C++)
- 深入php内核,从底层c语言剖析php实现原理
- 深入php内核,从底层c语言剖析php实现原理
- 深入php内核,从底层c语言剖析php实现原理
- 深入php内核,从底层c语言剖析php实现原理
- Clutter调用底层原理剖析
- 分布式事务底层原理剖析
- cocos2dx——节点的排序原理(sortAllChildren)(节点渲染顺序底层剖析)
- 【STL源码剖析读书笔记】自己实现stack之MyStack(底层用MyList)
- 【STL源码剖析读书笔记】自己实现queue之MyQueue(底层用MyList)
- 【STL源码剖析读书笔记】自己实现Heap算法之MyHeap(底层容器用vector)
- 使用C++,还是了解点底层比较好~:)[续1]
- TreeSet唯一性以及有序性底层剖析
- MJExtension底层实现原理简单剖析
- 腾讯笔试试题(编译原理部分)
- UIScrollView
- Django 1.5.4 专题24 Messages
- Velocity Template(一) VTL的hello,world程序
- HBase应用场景实例
- c++底层剖析(1)
- iOS实现长时间后台的两种方法
- HttpModule与HttpHandler详解
- 异常处理
- 自己动手写植物大战僵尸(iOS)
- EXCEL2013保存时提示Be careful!Parts of your document may include personal information...
- tar命令
- BigDecimal类数据的处理和"Non-terminating decimal expansion; no exact representable decimal result"问题
- jqueryui的accordion组件