数据段探究
数据段主要分为.bss(Block Started by Symbol)和.data(data segment)段,前者指用来存放程序中未初始化的全局变量的一块内存区域,后者是指用来存放程序中已初始化的全局变量的一块内存区域。
text和data段都在可执行文件中(在嵌入式系统里一般是固化在镜像文件中),由系统从可执行文件中加载 ,我们用段代码来确定
程序1:
1 2 3 4 5 int ar[30000 ];int main () { return 0 ; }
程序二:
1 2 3 4 5 int ar[30000 ];void main () { return 0 ; }
程序一的大小:
程序二的大小:
全局静态变量
我们先来看全局的静态变量,我们考虑初始化和未初始化两种情况,很明显他们存在.data段,并且是在程序加载进入main函数之前就初始化了,比如单例模式里的恶汉模式,所以就不必担心多线程问题
1 2 3 4 static int test = 1 ;int main () { return 0 ; }
1 2 3 4 5 6 7 sunxin@sunxin-KLVC-WXX9:~/static$ g++ test.cpp -g sunxin@sunxin-KLVC-WXX9:~/static$ gdb a.out (gdb) info addr test Symbol "test" is static storage at address 0x201010. (gdb) info symbol 0x201010 test in section .data
可以看到初始化的静态变量存在.data段,所以是在程序加载进入main函数之前就初始化了,由此也可以联想到单例模式里的恶汉模式,所以就不必担心多线程问题
如果没有赋值的全局静态变量是初始化在.bss里的:
1 2 3 4 static int test;int main () { return 0 ; }
1 2 3 4 (gdb) info addr test Symbol "test" is static storage at address 0x201018. (gdb) info symbol 0x201018 test in section .bss
接下来看一种在函数中初始化的全局静态变量,发现也是存在.bss区。
1 2 3 4 5 6 7 int foo () { return 1 ; } static int test = foo();int main () { return 0 ; }
1 2 3 4 (gdb) info addr test Symbol "test" is static storage at address 0x201138. (gdb) info symbol 0x201138 test in section .bss
对于以上代码,通过调试,我发现进入main函数前,test的值已经初始化为0了,进入main函数后test为1,说明 .bbs存储的是全局未初始化的变量,系统初始化为0当做一个占位符,而.data存的是初始化为自定义的变量
局部静态变量
关于局部静态变量的初始化就有些疑惑了,在c里静态变量都是在编译期间初始化完成,但是c++里就不太清楚了,网上很多答复是对象首次用到的时候构造初始化,接下来的代码我们来探究一下:
首先写个简单的局部静态变量
1 2 3 4 5 6 7 8 #include <iostream> using namespace std ;int main () { static int test = 1 ; static int no_test; static int no_test_2 = 0 ; return 0 ; }
1 2 3 4 5 6 7 8 (gdb) disas main Dump of assembler code for function main(): 0x000000000000073a <+0>: push %rbp 0x000000000000073b <+1>: mov %rsp,%rbp 0x000000000000073e <+4>: mov $0x0,%eax 0x0000000000000743 <+9>: pop %rbp 0x0000000000000744 <+10>: retq End of assembler dump.
通过汇编看不到main函数里对static变量初始化的语句,但进main函数前是查不到test的值的,说明局部静态变量是程序第一次碰到他的定义的时候,之后通过类似上面的办法,得出了静态变量的存储位置详见注释
类中静态变量
不多废话,直接通过代码分析:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class test { public : test(const char *name) : _name(name) { cout << _name << " created" << endl ; } ~test(){ cout << _name << " destroyed" << endl ; } string _name; }; test t ("global variable" ) ;void f () { static test t ("static variable" ) ; test t2 ("Local variable" ) ; cout << "Function executed" << endl ; } int main () { test t ("local to main" ) ; cout << "Program start" << endl ; f(); cout << "Program end" << endl ; return 0 ; }
1 2 3 4 5 6 7 8 9 10 11 global variable created local to main created Program start static variable created Local variable created Function executed Local variable destroyed Program end local to main destroyed static variable destroyed global variable destroyed
参考文献:https://www.cnblogs.com/mylinux/p/5611225.html
https://stackoverflow.com/questions/55510/when-do-function-level-static-variables-get-allocated-initialized