对静态变量和全局变量的认识

先看一小段程序:
#include<iostream>
using namespace std;

int nG = 1;
void Fun( )
{
    
static gg = 2;
    int local 
= gg;
}

int main( )
{                                      ----------------1
    
static int a = 3;
    
int b = nG;
    
int c = a;
    Fun( );
    
static oo = 4;
    c 
= oo;
    
return 0;    
}
     我们所关心的是这些变量如 nG  gg  a  等等在内存中的分布如何?它们都紧挨着放在一块?还是各有个的存储

    为了解决上述问题,首先提出第一个问题?
    Fun()中的局部静态变量 gg 在多次调用Fun()后(比如2次 )的值是多少?你肯定毫无犹豫地答到:  2
我如果问为什么?你可能毫无犹豫的答道:局部静态变量 gg  只是在第一次进入函数时被初始化。
  变量 gg 真的是在第一次进入 函数时才被初始化的吗??!!
 我们可以单步调试跟踪一下,你会发现调试时会直接跳过  static  gg = 2;这一行。
 因此我说变量 gg 在进入Fun函数之前就已经存在了,你信吗?
 我们可以将断点插在  1  处 ,调试  Alt  + 8 进入底层的汇编代码

12:       static int a = 3;               //对应着main函数中的声明,此时EBP = 0x0012FFC0
13:       int b = nG;
00404BB8   mov         eax,[nG (00476f90)]   //这两句给 b  赋值 ,可以发现全局变量 nG 的地址是:0x00476F90
00404BBD   mov         dword ptr [ebp-4],eax // b 的地址是 0x0012FFBC
14:       int c = a;
00404BC0   mov         ecx,dword ptr [nG+8 (00476f98)]  //这两句是给 a赋值,可以发现局部静态变量a的地址是
00404BC6   mov         dword ptr [ebp-8],ecx                     // 0x00476F98,c的地址是:0x0012FFB8
15:       Fun( );
00404BC9   call        @ILT+790(Fun) (0040131b)   --------看下面 Fun的汇编代码
16:       static oo = 4;
17:       c = oo;
00404BCE   mov         edx,dword ptr [nG+0Ch (00476f9c)]  //局部静态变量 oo的地址是 0x00476F9c
00404BD4   mov         dword ptr [ebp-8],edx
18:       return 0;
00404BD7   xor         eax,eax
19:   }

Fun的汇编代码:
7:        static gg = 2;
8:       int  local = gg;
004051B8   mov         eax,[nG+4 (00476f94)]//这两句在给local赋值,可以发现 局部静态变量 gg的地址是
004051BD   mov         [nG (00476f90)],eax     0x00476F94
9:    }
 由上述可以发现 变量 nG  gg  a  oo它们几个的内存地址很相近
0x00476F90:-----------------nG的地址
0x00476F94:-----------------gg的地址
0x00476F98:-----------------a   的地址
0x00476F9C:----------------oo的地址
我们可以发现这些全局变量和静态变量的内存地址,是在一块的。
总结:
  我们通常都说main函数是程序的入口点,所以就很容易造成一种误解。认为程序一运行就进入了main,这是
不对的。既然main是函数,是函数就得被调用了才能执行。那么是谁调用了main函数呢?
  通过调用堆栈我们发现,在main函数前还有一个函数:mainCRTStartup()。这个函数通常被称为启动代码,
  由他对程序在进入main函数之前进行初始化(如加载动态链接库分配资源等等),毕竟程序的正常运行不是
仅仅依靠小小的main就行的。当然初始化过程中包含对全局变量和静态变量的内存分配。这里的全局变量可能好理解,但是静态变量就有点难理解了。比如Fun中的 gg 他是一个局部静态变量啊 为什么会在进入main函数之前就被初始化啦。这就是静态变量的特性,这就是通常我们为什么说静态变量的生命周期,和整个程序的生命周期是一样的。
 下面简要的说一下本程序的运行流程:
  首先由启动代码完成一些必要资源的加载,和全局变量、静态变量(你程序中的所有静态变量,包括局部的)
  初始化,分配内存单元。
  进入main函数,首先进行的操作是在栈上分配一块内存单元,用来分配函数中的局部变量(除了静态变量)和
  参数的压栈以及函数地址的压栈。也就是说上面的main中的局部非静态变量 b  和   c就分配在此 内存块中,它   会在main函数返回后释放。
   同理在进入Fun函数时,首先也会在栈上分配一块内存单元,用来分配Fun函数中的局部变量(除了静态变       量)和参数的压栈以及函数地址的压栈。比如Fun中的local就分配在此段内存块中,它会在Fun函数返回以后
   被释放。
    最后return 0返回,释放分给main函数的内存块,main函数结束以后由mainCRTStartup( )完成全局变量和
   静态变量的释放,毕竟是由它调用mian函数的。
  最后再强调一下,Fun中的局部静态变量不是第一次进入Fun时被初始化的,而是在进入main函数之前就已经
  被初始化了。
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章