对“C++中何时对变量分配存储空间”的思考

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014633283/article/details/48596701

一、问题的引入

一直被“C++中变量的存储空间何时分配”困扰。在Visual studio2010中跑了一段代码,通过观察“监视窗口”中变量地址的变化和“内存窗口”,总结出一些自己的理解。


二、简单代码运行时的观察和总结

代码很简单,如下所示:

#include <iostream>
using namespace std;

int main()
{
     int a=0;
     cout << a <<endl;
     int *b = new int();
     int c=1;
     return 0;
}

在“监视窗口”中添加如下变量名:
监视窗口0
打开“内存窗口”如下所示:
内存窗口0
以下将按照调试(F10)的步骤展示“监视窗口”和“内存窗口”的变化,并提出我的理解。

step1:

当“调试光标”在第5行时(尚未进入函数):
调试5
“监视窗口”如下:
监视5
此时仍没有给各变量分配内存空间,原因是“堆栈帧还没有被分配”。

step2:

当“调试光标”在第6行时(执行完第5行,刚进入函数):
调试6
“监视窗口”如下:
监视6
对比step1,我们发现,除了*b,其他变量名的值都发生了变化,可以得出如下结论:

  • 在一进入函数时,所有变量的内存空间便分配了,如&a,&b,&c。a=0的显示初始化是在a,b,c内存空间都分配完成后才进行;
  • 尽管*b是没有意义的(没有分配存储空间),但b作为一个指针变量,却是和a,b等普通变量一样分配了内存空间;
  • 注意a的值为-858993460,其16进制表示即为0xcccccccc。也就是说,变量在初始化时每个字节被赋成0xcc。

打开“内存窗口”,查看0x002af890处的内存如下图所示:
内存6
从中我们可以得出如下结论:

  • 变量内存空间的分配,是按照往地址减小的方向进行,这可能和“栈的生长方向有关”

step3:

当“调试光标”在第7行时(执行完第6行):
调试7
“监视窗口”如下:
监视7
a的值发生了变化
此时,我们再去观察内存0x2af8a8处的内存,如下图红线标注所示,都变为0
内存7

step4:

当“调试光标”在第9行时(执行完第7行和第8行):
调试9
“监视窗口”和0x002af89c处的内存如下:
监视9
内存9
对比step3中的监视窗口,可以发现b和*b的值都发生了变化,可以得出以下结论:

  • 在int*b定义指针时,b指针的值是未定义的(也就是野指针),查看step3中b指针0xcccccccc所指向的内存单元,如下图所示,可以发现是不确定的值,因而对“野指针”的使用时不安全的:野指针
  • new关键字对指针进行初始化(如内存窗口中红色数字所示),并且会对*b初始化为0,查看b指针0x00364CE8所指向的内存单元,如下图红线标注所示:*b处内存
  • 观察图片“内存9”中0x002af89c处的内存,可以发现高位字节(0x00)在高地址(0x002AF89F)处,低位字节(0xe8)在低地址(0x002AF89C)处,因而内存中采用“小端法”;
  • 查看&b值0x002AF89c的内存,可以发现其存储0x00364ce8,也就是b指针的值,再查看0x00364ce8的内存单元,可以发现其存储0x00000000,也就是*b的值。

step5:

当“调试光标”在第10行时(执行完第9行):
调试10
“监视窗口”如下
监视10
其中只有c的值发生了变化

猜你喜欢

转载自blog.csdn.net/u014633283/article/details/48596701