谈谈全局变量、静态变量的初始化问题

经常性的在面试和笔记题目中会看到全局变量、静态全局变量、静态变量的存储位置和初始化时间的问题,

一般都能答出来他们存储位置,但可能有很多人不清楚这些变量是什么时候初始化的,下面我们从代码角度来看看,这些变量是什么时候初始化的,

如果在main函数之前初始化,那么又是如何做的。

samplecode定义如下:

MyClass g_A;
int g_nTest2 = 1;
int main()
{
return  0;
}

1.类对象初始化 先来看下那个g_A在什么时候初始化和调用构造函数 

在main之前还有另外一个函数:(w)mainCRTStartup需要调用(crt的main入口),代码如下:

int mainCRTStartup(void)
{
        /*
         * The /GS security cookie must be initialized before any exception
         * handling targetting the current image is registered.  No function
         * using exception handling can be called in the current image until
         * after __security_init_cookie has been called.
         */
        __security_init_cookie();

        return __tmainCRTStartup();
}

第一行security_init_cookie就是初始化缓冲区溢出检查的cookie值,这个cookie具体有什么用,可以看我另外一篇文章( http://blog.csdn.net/zhuobattle/article/details/17373521)

然后就是调用__tmainCRTStartup,

__tmainCRTStartup这个函数里会有如下代码来做C++初始化:

/*
            * do C++ constructors (initializers) specific to this EXE
            */
            if (__native_startup_state == __initializing)
            {
                _initterm( __xc_a, __xc_z );
                __native_startup_state = __initialized;
            }

调用完后,才会去调用main函数:

            mainret = main(argc, argv, envp);

g_A的构造函数就在_inititerm函数里去调用,具体有兴趣可以去看源码(X:\Program Files\Microsoft Visual Studio 8\VC\crt\src\crtexe.c)

2. 已初始化的 全局变量(静态变量) 那么有人会问,像如下的全局变量什么时候初始化呢:


int g_nTest2 = 1;

答案是这些已知类型的变量在PE文件中已经被硬编码了那个值,g_nTest2被硬编码成了1,

如果要证实可以用调试工具去看下那个地址的值是什么时候写入的。

用OD载入(第一次暂停记得选择在系统断点)为了方便,我选择了如下的测试代码:

int g_nTest2 = 0x001200FE;

void TestGolabal()
{
	static int gA2 = 0x003400AB;
...
}	

包括全局和静态变量,

系统断点下来,我们会看到,那个全局变量对应的地址早就被赋值了,如下图:


直接打开PE文件,我们也看到了如下的值:



3.未初始化全局变量

未初始化的全局变量gcc编译器中会分配一个 .bss section,在PE被加载时会根据PE header信息分配空间,

并初始化为0,但是VC编译器编译出来的并没有.bss节,未初始化的全局静态量也在.data段中


总结下,class等这些全局变量是在main函数之前,在__tmainCRTStartup里调用的构造函数进行初始化;

而像int等已知类型的已初始化全局变量和静态变量它的值已经写在PE文件里了,PE Loader加载时就已经写

入,未初始化的全局和静态变量则也是在PE加载时为其分配空间,并初始化成0.具体我们要看下PE加载逻辑了。

对于PE加载逻辑以后整理下。



  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言中有四种类型的变量:局部变量全局变量静态局部变量静态全局变量。 1. 局部变量(Local Variables): 局部变量是在函数内部声明的变量,它们只在函数内部可见和访问。局部变量的作用域仅限于声明它们的函数内部。当函数执行完毕后,局部变量会被销毁,其占用的内存也会被释放。 2. 全局变量(Global Variables): 全局变量是在函数外部声明的变量,它们可以被程序中的所有函数访问。全局变量的作用域从声明开始的地方一直延伸到文件的末尾。全局变量在整个程序的执行过程中都是存在的,因此会占用内存。需要注意的是,在多个文件中使用同名的全局变量会导致冲突,因此应该避免这样的情况发生。 3. 静态局部变量(Static Local Variables): 静态局部变量与普通局部变量相似,都是在函数内部声明。不同之处在于,静态局部变量只会在首次进入该函数时进行初始化,之后的函数调用不会重新初始化变量。同时,静态局部变量的作用域仍然限制在声明它们的函数内部,但是其生命周期会延长到整个程序的执行过程。 4. 静态全局变量(Static Global Variables): 静态全局变量与普通全局变量相似,都是在函数外部声明。不同之处在于,静态全局变量只能在声明它们的文件内部访问,其作用域被限制在当前文件范围内。其他文件无法访问该变量静态全局变量会在程序开始执行时进行初始化,并且在整个程序执行期间都存在。 以上就是C语言中四种不同类型的变量:局部变量全局变量静态局部变量静态全局变量的特点和用法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值