to quit--- 0x80495b0 <_ZL7gs_buf1+80>: 0 0 0 0
0x80495c0 <_ZL7gs_buf1+96>: 0 0 0 0
0x80495d0 <_ZL7gs_buf1+112>: 0 0 0 0
0x80495e0 <_ZL7gs_buf1+128>: 0 0 0 0
0x80495f0 <_ZL7gs_buf1+144>: 0 0 0 0
0x8049600 <_ZL7gs_buf1+160>: 0 0 0 0
0x8049610 <_ZL7gs_buf1+176>: 0 0 0 0
0x8049620 <_ZL7gs_buf1+192>: 0 0 0 0
0x8049630 <_ZL7gs_buf1+208>: 0 0 0 0
0x8049640 <_ZL7gs_buf1+224>: 0 0 0 0
0x8049650: 0 0 0 0
0x8049660 <_ZZ4mainE5base1>: 0 0 0 0
0x8049670 <_ZZ4mainE5base1+16>: 0 0 0 0
0x8049680 <_ZZ4mainE5base1+32>: 0 0 0 0
0x8049690 <_ZZ4mainE5base1+48>: 0 0 0 0
0x80496a0 <_ZZ4mainE5base1+64>: 0 0 0 0
0x80496b0 <_ZZ4mainE5base1+80>: 0 0 0 0
0x80496c0 <_ZZ4mainE5base1+96>: 0 0 0 0
0x80496d0: 0 0 0 0
0x80496e0 <_ZZ4mainE5temp1>: 0 0 0 0
0x80496f0 <_ZZ4mainE5temp1+16>: 0 0 0 0
0x8049700 <_ZZ4mainE5temp1+32>: 0 0 0 0
0x8049710: 0 0 0 0
0x8049720 <_ZZ4mainE4base>: 0 0 0 0
0x8049730 <_ZZ4mainE4base+16>: 0 0 0 0
0x8049740 <_ZZ4mainE4base+32>: 0 0 0 0
0x8049750 <_ZZ4mainE4base+48>: 0 0 0 0
0x8049760 <_ZZ4mainE4base+64>: 0 0 0 0
0x8049770 <_ZZ4mainE4base+80>: 0 0 0 0
0x8049780 <_ZZ4mainE4base+96>: 0 0 0 0
0x8049790: 0 0 0 0
0x80497a0 <_ZZ4funcvE2s1>: 0 0 0 0
0x80497b0 <_ZZ4funcvE2s1+16>: 0 0 0 0
0x80497c0 <_ZZ4funcvE2s1+32>: 0 0 0 0
0x80497d0: 0 0 0 0
0x80497e0: 0 0 0 0
0x80497f0: 0 0 0 0
0x8049800: 0 0 0 0
0x8049810: 0 0 0 0
0x8049820: 0 0 0 0
0x8049830: 0 0 0 0
0x8049840: 0 0 0 0
0x8049850: 0 0 0 0
分析结果:
全局变量与静态变量的唯一区别在于链接属性,全局变量为外部链接属性,全局静态变量(类内部的静态变量)为内部链接属性,函数内部的静态变量无链接属性。
注:对于类内部的静态变量,类名相当于一个命名空间,而全局静态变量的命名空间为::(全局命名空间),所以它们本质上无差别!
全局变量和静态变量内存布局基本相同,这里一并考虑。
全局/静态变量的内存分配主要是遵循一个大的原则,将初始化的和未初始化的变量分开存放,初始化的变量被放在全局数据区,未初始化的变量放在BSS段,这样有一个好处,BSS段在文件中是没有大小的,只有一个地址,所有未初始化的全局静态变量都指向这个地址,这样可以减小文件的大小。而在运行时,才会为BSS段分配内存空间,并且全部初始化为0,所以未初始化的全局/静态变量载入内存后,默认值为0。
然后我们看内存布局:
前面4个变量依次是,g_buf3,_ZZ4mainE1b,_ZZ4mainE1a和_ZZ4funcvE2s2,编译器在编译时为了防止名称冲突,会对变量函数名进行名称修饰,linux下可用c++filt工具进行还原。
还原后的变量依次是:
g_buf3,main函数中的静态变量b、a和func中的静态变量s2。
这4个是初始化了的全局/静态变量,所以被放在全局初始化区,这里我们得出以下几点结论。
1、可以发现s2和s3都被初始化了,可是只有s2被分配内存空间,而s3并未分配内存空间,这是因为linux中为静态变量分配内存是根据该变量是否被使用来判断的,如果一个静态变量定义后,未发现它被其它变量引用了,将不会为其分配内存空间。
2、对于全局变量,不管它是否被使用了,都会为其分配内存空间。
3、在函数中的静态变量,在内存中的顺序恰恰和它们在函数中的声明顺序相反(目前尚不知这样做的原因)。
这里有一个疑问,g_base和gs_base这两个变量被初始化了,为什么它们被放在未初始化的全局数据区。这是因为g_base和gs_base这两个变量是在运行时通过调用构造函数被初始化的,在编译时我们是无法知道它们的值的,所以在编译时它们也被放在了BSS段。所以这里得出结论:
4、全局/静态类变量在内存中被放在未初始化数据区。
下面我们看看未初始化数据区里面的变量,依次是
g_buf1、g_buf2、g_base、gs_base、main函数的base1、temp1、base,func函数的s1。
可以看到g_base、gs_base值不为0,而base1,base的值为0,因为我的断点是在main函数入口处设置的,所以全局类变量的构造函数已被调用过了,而main函数内的类变量的构造函数尚未调用,但是它们的内存空间已被分配,这印证了以上结论4。