VC++ 内存布局 运行原理 基础的东西 整理一下

以下仅仅是个人分析理解的观点,如有不正确之处,请予指出,多谢!

#include <iostream>
using namespace std;
/*
首先分析 vc++ 在运行期间内存布局

将定义部分 全部放在内存空间中 也可以说先铺下一个结构
理由:根据测试得知 程序一启动 由于加入了int nnnp[102400]   所以该exe占用内存空间加大了400K左右
所以 非声明而是定义  但是这里定义放在内存中的那部分就不清楚了,至少它有大小限制
在做对象定义的时候 比如 B d;
其实是首先将一个内存地址也就是d 放到B的结构内,调用B来的构造函数,以后如果调用其他函数申请了新的内存 都关联到d中

编译过程中 把对象之类的非动态申请内存(new malloc)的语句 也放在了内存空间中
理由: B b3[1]; 写入在main()函数内部,程序一启动的时候 还没有运行到它 内存就增长了

B b;
D *pd = (D*)&b;
pd->vf();
pd->va2();
强制转换后
当调用 vf() 时候 根据查看汇编代码可知
在程序运行内存布局期间,它将所有转跳 都写在一个区域 jump XXX
也就是 布局定义是一个区域 转跳是一个区域
00401XXX 存储的是 class B D C 的定义
00402XXX 存储的是 所有转跳 jump B() ~B() B:vf() D() D:vf()等
pd->vf() 所做的操作是 将pd 所指向的内存地址给寄存器ecx,也就是b的地址
然后调用jump D:vf()  在D:vf() 函数内部 如果需要变量等数据 则根据ecx中传递的地址 去提取 (转跳原理 首先记录下跳之前的地址,在跳到函数内,执行完 在跳回调之前记录的地址中,这个原理就是简单的破解注册)
但是 如果D:vf() 仅仅是cout<<"aa" 之类的话 跟数据地址无关,则直接执行。(这里先不加入虚函数的概念)
pd->va2();
这里是要输出i1 虽然D没有实例化 但是B实例化了 并且这个函数输出i1的数据地址B能够给出 所以可以执行

举个更明显的例子:
C* pc = NULL;
pc->vfc();
pc->vfc2(); vfc2中存在了变量 如果想正常执行 就必须给他定义成为静态成员函数,呵呵这就是静态的好处

*/
class B
{
public:  
 int nnnp[102400];
 int i1;
 B()
 {
  i1 = 11;
  cout << "构造 B" << endl;
  cout<<i1<<endl;
  cout<<&i1<<endl;
 }
 void vf()
 {
  cout << "This is class B" << endl;
 }

 virtual  ~B()
 {
  cout << "析构 B" << endl;
 }
};

class D: public B

public:
// int i1;
 D()
 {
  i1 =2;
  cout << "构造 D" << endl;
  cout<<i1<<endl;
 }
 void vf()
 {
  cout << "This is class D" << endl;
 }
 void va()
 {
  cout << "This is class D va" << endl;
 }
 void va2()
 {
  cout <<i1<< endl;
  cout<<&i1<<endl;
 }
 ~D()
 {
  cout << "析构 D" << endl;
 }
};

class C
{
public:
 void vfc()
 {
  cout<<"Class c"<<endl;
 }
 static void vfc2()
 {
  char p = 'c';
  cout<<"Class c:"<<p<<endl;
 }
};
main()

 cin.get();
 B b;
// cout<<&b<<endl;

 D *pd = NULL;
 pd = (D*)&b;
// cout<<&pd<<endl;
 pd->vf();
 pd->va2();

 C* pc  = NULL;
 pc->vfc();
 pc->vfc2();
 
 B b3[1];
// char *p = new char[10240];
 cin.get();
}
/*
疑问1
 pb = &d;  不需要转换
 即可指向d的地址
 原因 d是b的继承类 按照继承类的特性 d的覆盖范围包含b
 所以pb 可调用的函数 都是b中的 并且d中指定都含有了 所以 没问题

    以下理解错误
 pd = (D*)&b;     需要转换
 即不可指向b的地址
 原因pd是d的指针,可以调用b中及d的方法,但是d中的方法b中不一定全部含有
 所以必须需要转换一下
 正确: 强制转换 就是强制转换 不关心数据类型
疑问2
在非多态前提下
 pb = &d;
 pb->vf();
 输出结果是 b
 是否可以这样理解: 指针或对象 决定了它的 活动范围,
限制:
 B的指针或对象 就只能在B类范围内活动
 D的指针或对像 就只能在D类范围内活动
 
 虽然D.vf函数 覆盖了B.vf()
 但是由于限制前提 所以 pb 输出仍然是b
以上太牵强了
问题2解决 看开头叙述部分
*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值