static静态局部变量初始化问题
第一次写博客之类的东西,主要是为了记录自己的学习过程,以便于记忆的加深和与各位大神进行探讨,学习更多的东西。
本次上传主要是关于静态局部变量的初始化问题。
首先,静态局部变量和全局变量一样,数据都存放在全局区域,所以在主程序之前,编译器已经为其分配好了内存,但在C和C++中静态局部变量的初始化节点又有点不太一样。在C中,初始化发生在代码执行之前,编译阶段分配好内存之后,就会进行初始化,所以我们看到在C语言中无法使用变量对静态局部变量进行初始化,在程序运行结束,变量所处的全局内存会被全部回收。而在C++中,初始化时在执行相关代码时才会进行初始化,主要是由于C++引入对象后,要进行初始化必须执行相应构造函数和析构函数,在构造函数或析构函数中经常会需要进行某些程序中需要进行的特定操作,并非简单地分配内存。所以C++标准定为全局或静态对象是有首次用到时才会进行构造,并通过atexit()来管理。在程序结束,按照构造顺序反方向进行逐个析构。所以在C++中是可以使用变量对静态局部变量进行初始化的。
后面再来谈谈另一个问题,假如我们在一个循环中,定义了一个静态局部变量并进行初始化,循环过程中,编译器怎么知道当前的静态局部变量已经初始化过了呢?
这个问题C和C++的处理方式也是不一样的。C中编译器会直接跳过这一个语句,因为在编译的时候已经对静态局部变量进行过分配空间并初始化,所以代码执行过程中根本不需要再次执行。而在C++中,编译器会在编译器分配内存后,在全局区域(当前静态局部变量的地址)附近同样分配一块空间,进行记录变量是否已经进行过初始化。之所以说附近是根据编译器不同,处理方式不同导致的。在网上有博客介绍某种编译器(该吧主并没有透露编译器名字),会在当前变量后面的一个字节进行改变,具体上代码:
(Ps:若编译器已经发现当前变量初始化,则直接将整行代码跳过,若等式后面为n++,则不会继续执行++命令)
从地址内存中我们可以看到在变量地址的后面一个字节中,有一个01用来记载当前静态变量是否初始化。
而在VS2012中,发现了一个很奇怪的现象,先上代码。
这段代码a为变量,右侧为执行代码的汇编语句,可以看到先从0x00306214中提取出来值,如果是0,则会继续执行,进行初始化,如果是1,则会跳过当前下面的动作,此处可以看到标志位地址是在变量地址之前0x80个字节,但继续后面几种情况
可以看到只要变量名称发生改变,每次标志位所在的地址与变量地址之间的差距变化都比较大。可见VS编译器对标志位地址的选择是根据变量名称变化的。具体选择方法,还希望有钻研过的大神指点一二。
上面说到的仅仅针对单线程的程序,如果在多线程下的执行,g++编译器会在在初始化过程中对标志位进行加锁控制,详情参考一下 http://www.cnblogs.com/xuxm2007/p/4652944.html
在不确定编译器是否会对多线程环境下静态局部变量初始化加锁的情况下,尽量不要使用初始化的局部静态变量,如果需要使用,则需要自己定义一个全局锁进行管控,如一个线程正在对某个变量(对象)进行构造,另一个线程需要直接避开构造。
第一次发此类分享类博客,如果有大神看出其中漏洞,请及时指出,以便于本人能够对这方面的了解更加深入
补充:使用G++调试后,查看地址发现对于一个静态局部变量,编译器会开辟8个字节的大小的存放空间,同时存放位置刚好在变量前面的8个字节位置。若有两个静态局部变量,则从第一个静态局部变量前16个字节,分别8个字节对应一个变量。用事实说话,上图:
static静态局部变量初始化问题的更多相关文章
- static静态全局变量和static静态局部变量
static静态全局变量: 静态全局变量就是将全局变量变成静态的.如何变?——全局变量加个static. static就是一个存储类说明符,a这个全局变量就成了一个静态全局变量了. 静态全局变量的特点 ...
- PHP static静态局部变量和静态全局变量总结
1.不会随着函数的调用和退出而发生变化,不过,尽管该变量还继续存在,但不能使用它.倘若再次调用定义它的函数时,它又可继续使用,而且保存了前次被调用后留下的值 2.静态局部变量只会初始化一次 3.静态属 ...
- PHP之static静态变量详解(一)
什么是static静态变量?(以下为在C语言中的理解) 静态变量 类型说明符是static. 静态变量属于静态存储方式,其存储空间为内存中的静态数据区(在静态存储区内分配存储单元),该 区域中的数据在 ...
- c语言局部变量 静态局部变量 全局变量与静态全局变量
基本概念: 作用域:起作用的区域,也就是可以工作的范围. 代码块:所谓代码块,就是用{}括起来的一段代码. 数据段:数据段存的是数,像全局变量就是存在数据段的 代码段:存的是程序代码,一般是只读的. ...
- 静态局部变量(面向过程的static关键字)
对于一个完整的程序,在内存中的分布情况如下图: 一般程序的由new产生的动态数据存放在堆区,函数内部的自动变量存放在栈区.自动变量一般会随函数的退出而释放空间,静态数据(即使是函数内部的静态局部变量) ...
- 单片机之静态局部变量static
HL-1慧静电子 上程序: main.c #include <reg52.h>#include "Timer.h" /********P1口低有效*********** ...
- C++ 全局变量、局部变量、静态全局变量、静态局部变量的区别
全局变量.局部变量.静态全局变量.静态局部变量的区别 C++变量根据定义的位置的不同的生命周期,具有不同的作用域,作用域可分为6种:全局作用域,局部作用域,语句作用域,类作用域,命名空间作用域和文件作 ...
- static静态变量的理解
静态变量 类型说明符是static.静态变量属于静态存储方式,其存储空间为内存中的静态数据区(在 静态存储区内分配存储单元),该区域中的数据在整个程序的运行期间一直占用这些存储空间(在程序整个运行期间 ...
- 静态局部变量、静态全局变量、extern全局变量、自动变量 札记
静态局部变量 静态局部变量. 从称呼上我们可以看出,静态局部变量首先是一个局部变量,因此其只在定义它的函数内有效,冠以静态的头衔后,其生存期就被延长了,不会随着函数的返回而被撤销.我们可以这样来理解: ...
随机推荐
- winform 子窗体刷新父窗体的数据
建一个接口 比如 iMainForm接口内声明个方法 比如 Refresh()主窗体 实现这个接口 主窗体打开子窗体时这样写 子窗体.Owner = this;子窗体.ShowDialog(); -- ...
- JZ2440 裸机驱动 第14章 ADC和触摸屏接口
本章目标: 了解S3C2410/S3C2440和触摸屏的结构: 了解电阻触摸屏的工作原理和等效电路图: 了解S3C2410/S3C2440触摸屏控制器的多种工作模式: ...
- jquery.validate.js remote (php)
网上的人不厚道呀 validate 这玩意的异步是 返回的 echo 'true' 或者 echo 'false';很少有人说呀~.~ 转载了一篇原文: jquery.validate.js对于数 ...
- dedecms问答模块时间显示1970-01-01的解决办法
在使用dedecms的问答模块的时候,很多人希望能在模板上加上问题的时间,一般我们采用这样的dede标签: {dede:ask row=24 titlelen='50' sort='ok'} &l ...
- Centos替换默认源
将默认的国外源替换为国内的网易的源 参考帮助文档:http://mirrors.163.com/.help/centos.html 查看本机版本:cat /etc/redhat-release 先安装 ...
- linux 静态库文件
1.生成目标文件 gcc -o mylib.o -c mylib.c 2.生成静态库文件 ar rcs libmylib.a mylib.o 查看库信息: nm libmylib.a //====== ...
- [转]修改DLL
部分内容来自:http://blog.csdn.net/csdncshuan/article/details/51477705 为没有源码的DLL文件添加强名称 如果项目中引用了其他没有源码的dll文 ...
- Python 标准库 ConfigParser 模块 的使用
Python 标准库 ConfigParser 模块 的使用 demo #!/usr/bin/env python # coding=utf-8 import ConfigParser import ...
- 将ESXI所有的端口组迁移到分布式交换机的步骤
1.如果是DELL服务器,一般有2-4个网口,那么所有的网口都把网线插到交换机上:2.DELL安装ESXI系统,根据不同的DELL硬件,要安装不同的ESXI版本.原则上越高版本,支持的硬件越多向下兼容 ...
- centos7 设置系统时间与网络同步
1.安装ntpdate工具 yum -y install ntp ntpdate 2.设置系统时间与网络时间同步 ntpdate cn.pool.ntp.org 3.将系统时间写入硬件时间 hwclo ...