Adblocker

4.7.栈对象与堆对象的定义

程序来自于《C++反汇编揭秘》

目录

4.7.栈对象与堆对象的定义

1.栈对象

2.堆对象


 

1.栈对象

【示例代码1】

#include "stdafx.h"

class CNumber {
public:
    CNumber() {
        m_number = 1;   //无参构造函数
    }
    int m_number;
};
void main()
{
    CNumber Number; //类对象定义
}

 

x86-debug版本反汇编代码如下:
主函数代码如下:

java对象堆栈 栈对象 堆对象_信息安全

类对象的调用如下:

java对象堆栈 栈对象 堆对象_成员变量_02

x86-debug版本的堆栈结构图如下:

java对象堆栈 栈对象 堆对象_实例化_03

x86-release版本:

java对象堆栈 栈对象 堆对象_实例化_04

 

分析:

(1)相较于debug版本,debug版本就省事多了,由于类没有任何操作,就直接把类的相关操作给省略了。

(x64版本的结构类似)

(2)类的定义其实就是一个模板,当实例化对象时才开始产生对应的内存空间。

(3)当调用类的构造函数的时候,会“偷偷”的将对象的首地址通过ecx(一般是这个)传递给构造函数,即this指针的由来;因此this指针其实就是实例化后对象的首地址。

(4)实例化对象后成员变量的赋值,类中第一个定义的成员变量地址=类首地址,其后的的成员变量地址在内存空间中按照定义顺序依次向地址增大的方向。先定义的在小地址,后定义的在大地址,因此第一个定义的就是首地址啦!

例如假设类中依次定义了变量:  char cChar; int nInt;  int m_one;   那么其地址分布如下:

java对象堆栈 栈对象 堆对象_信息安全_05

 

2.堆对象

【示例代码2】

#include "stdafx.h"

class CNumber {
public:
    CNumber() {
        m_number = 1;   //无参构造函数
    }
    int m_number;
};
void main()
{
    CNumber * pNumber = NULL;
    pNumber = new CNumber;
    pNumber->m_number = 2;
    printf("%d \r\n", pNumber->m_number);
}

 

x86-debug版本如下:

java对象堆栈 栈对象 堆对象_信息安全_06

分析:

栈对象和堆对象在定义时编译器都会自动申请空间,但是堆对象增加了一个“双分支”检测语句,检测堆空间分配是否成功,如果成功,则将成功后的堆空间首地址赋给对象指针;如果失败,则将NULL赋值给对象指针。(堆申请空间分配语句如下:)

java对象堆栈 栈对象 堆对象_反汇编_07

x86-release版本:

(这个版本中直接将“try”保护给省去了,个人觉得是因为事先已将判断堆空间可以申请成功,因此在运行结束后将堆申请检测操作给省去了)

java对象堆栈 栈对象 堆对象_java对象堆栈_08

 

 

  • 1.栈对象
  • 2.堆对象