static静态局部变量初始化问题

第一次写博客之类的东西,主要是为了记录本身的学习过程,以便于记忆的加深和与各位大神进行探讨,学习更多的东西。html

  

本次上传主要是关于静态局部变量的初始化问题。多线程

首先,静态局部变量和全局变量同样,数据都存放在全局区域,因此在主程序以前,编译器已经为其分配好了内存,但在C和C++中静态局部变量的初始化节点又有点不太同样。在C中,初始化发生在代码执行以前,编译阶段分配好内存以后,就会进行初始化,因此咱们看到在C语言中没法使用变量对静态局部变量进行初始化,在程序运行结束,变量所处的全局内存会被所有回收。而在C++中,初始化时在执行相关代码时才会进行初始化,主要是因为C++引入对象后,要进行初始化必须执行相应构造函数和析构函数,在构造函数或析构函数中常常会须要进行某些程序中须要进行的特定操做,并不是简单地分配内存。因此C++标准定为全局或静态对象是有首次用到时才会进行构造,并经过atexit()来管理。在程序结束,按照构造顺序反方向进行逐个析构。因此在C++中是能够使用变量对静态局部变量进行初始化的。函数

 

后面再来谈谈另外一个问题,假如咱们在一个循环中,定义了一个静态局部变量并进行初始化,循环过程当中,编译器怎么知道当前的静态局部变量已经初始化过了呢?学习

这个问题C和C++的处理方式也是不同的。C中编译器会直接跳过这一个语句,由于在编译的时候已经对静态局部变量进行过度配空间并初始化,因此代码执行过程当中根本不须要再次执行。而在C++中,编译器会在编译器分配内存后,在全局区域(当前静态局部变量的地址)附近一样分配一块空间,进行记录变量是否已经进行过初始化。之因此说附近是根据编译器不一样,处理方式不一样致使的。在网上有博客介绍某种编译器(该吧主并无透露编译器名字),会在当前变量后面的一个字节进行改变,具体上代码:spa

(Ps:若编译器已经发现当前变量初始化,则直接将整行代码跳过,若等式后面为n++,则不会继续执行++命令)线程

 

从地址内存中咱们能够看到在变量地址的后面一个字节中,有一个01用来记载当前静态变量是否初始化。调试

而在VS2012中,发现了一个很奇怪的现象,先上代码。htm

 

 

这段代码a为变量,右侧为执行代码的汇编语句,能够看到先从0x00306214中提取出来值,若是是0,则会继续执行,进行初始化,若是是1,则会跳过当前下面的动做,此处能够看到标志位地址是在变量地址以前0x80个字节,但继续后面几种状况对象

 

 

 

能够看到只要变量名称发生改变,每次标志位所在的地址与变量地址之间的差距变化都比较大。可见VS编译器对标志位地址的选择是根据变量名称变化的。具体选择方法,还但愿有钻研过的大神指点一二。blog

 

上面说到的仅仅针对单线程的程序,若是在多线程下的执行,g++编译器会在在初始化过程当中对标志位进行加锁控制,详情参考一下 http://www.cnblogs.com/xuxm2007/p/4652944.html

在不肯定编译器是否会对多线程环境下静态局部变量初始化加锁的状况下,尽可能不要使用初始化的局部静态变量,若是须要使用,则须要本身定义一个全局锁进行管控,如一个线程正在对某个变量(对象)进行构造,另外一个线程须要直接避开构造。

 

 第一次发此类分享类博客,若是有大神看出其中漏洞,请及时指出,以便于本人可以对这方面的了解更加深刻

 

补充:使用G++调试后,查看地址发现对于一个静态局部变量,编译器会开辟8个字节的大小的存放空间,同时存放位置恰好在变量前面的8个字节位置。如有两个静态局部变量,则从第一个静态局部变量前16个字节,分别8个字节对应一个变量。用事实说话,上图:

相关文章
相关标签/搜索