在编写程序时,内存的控制是很重要的一部分。关于全局变量和局部变量,静态变量的关系如何?以及他们在内存在是存储于哪部分的?做个记录,以便往后查看。

1. 全局变量和静态变量

全局变量:又称外部变量,与之相对的是局部变量,是从变量的作用域上来考量的。全局变量定义与函数外面,作用于整个程序;而局部变量则是定义在函数里面,仅作用于函数内部,无法跨函数作用。全局变量为静态分配,即程序执行之前就进行内存分配,不再改变(内存不再改变);而局部变量则是动态分配,在程序执行的时候进行内存分配。

静态变量:是从变量的内存分配上来考量的,与之相对的是动态变量。静态变量如其名,采用静态分配方式的变量,表现在代码程层面就是用 static 或 extern 关键字修饰的变量即为静态变量。静态变量分为static和extern,两者作用域不同,static修饰的只能作用于单个程序文件,而extern 则可以作用于整个程序(多文件)。

 全局变量和静态全局变量:当程序只有一个文件构成时,两个没有什么区别;当多个文件存在时,static全局变量则使得该变量为源文件独享(只作用于单个文件),而 extern 全局变量则可以作用整个程序,包括其他源文件。

那么静态局部变量呢?静态局部变量作用域与局部变量一致,只不过生命周期不一样,内存存储地点也不一样。静态局部变量是程序执行之前静态分配内存,程序执行结束之后结束。

看到有人提到静态变量无法改变,这是错误的。静态变量只是内存分配为静态分配方式,内存不变,并不是说不可以改变,静态变量也是可以更改存储内容的。

2. 全局变量,静态变量在内存中存放位置

我们知道一个汇编程序分为:代码段,数据段,堆栈段(这里的堆栈就是指的栈,stack)。从内存上说,数据段又可分为:静态存储区,堆(heap)和BSS(Block Started by Symbol)区。

代码段:就是存放程序二进制代码区域

静态存储区(.data):用于存放已初始化的全局变量和静态变量

堆(heap):数据区,用于动态分配的存储。一般由程序员控制分配和释放,malloc 和 new 的数据存放于堆中

未初始化全局(静态)变量BSS:未初始化的全局变量和静态变量,全局变量和静态变量默认初始化为0

堆栈(stack):通常理解就是局部变量,函数调用等所需存储

为了了解全局变量和静态变量等内存存储位置,talk is cheap, show the code! 给出一个测试案例,然后用objdump 或者 readelf反汇编指令,进行查看该程序生成的对应汇编程序结构,获取各个变量的内存段分配。

// tets.c
#include <stdio.h>static int var_global_static_a = 1;  // 初始化静态全局变量
static int var_global_static_b;      // 未初始化静态全局变量int var_global_a = 1;                // 初始化全局变量
int var_global_b;                    // 未初始化全局变量int main()
{static int var_static_a = 1;    // 初始化静态局部变量static int var_static_b;        // 未初始化静态局部变量int var_a = 1;                  // 初始化局部变量int var_b;                      // 未初始化局部变量return 0;
}

结果如下图所示:

objdump -t test.o

执行结果可知:已初始化的全局变量和静态变量(无论全局还是局部)都是存放于.data 段,而未初始化的静态变量则是存放在.bss 段,未初始化的全局变量存放在 .comment,这个不知道是干嘛的,但其实也是应该是 .bss 类似。而局部变量则并未出现在这里,因为局部变量位于堆栈段,是需要程序执行时进行分配的,所以这个只进行了编译的obj文件中并没有这两个变量的内存分配。

.data var_global_static_a 初始化全局变量和静态变量
var_static_a
var_global_a
.bss var_global_static_b 未初始化全局变量和静态变量
var_static_b
var_global_b (显示是 .COM)
未分配 var_a 局部变量
var_b

如果全局变量初始化都为 0 呢?结果如下所示,全部都变成了 .bss 段。其实0是全局变量和静态变量的默认初始化值,即如果没有主动初始化而直接使用,则是默认初始化为0 。所以当主动初始化为0时,还是当成没有初始化处理,存放于 .bss 段

3.  堆(heap)和堆栈段(stack)

堆和栈总是一起别人提起,所以这里也放在一起来讲。有个概念需要区分开的,就是堆栈指的就是内存的stack部分,而不是堆和栈,堆是heap。有时候定义数组,因为过大,直接定义成局部变量的话就会爆,但是用 malloc 或者将数组变为全局变量,就不会爆。我们知道这这分别对应着堆栈存储 和 数据段(堆 和 静态存储区),那么他们的大小分别是多少呢?

3.1 堆的大小和堆溢出

堆作为数据段的一部分,理论上除去堆栈大小,代码段大小和全局变量静态变量等部分,剩下的都可以作为堆的内存分配范围。所以堆的大小一般比较大,几乎接近计算机内存(+虚拟内存)大小。关于堆溢出,如果持续进行 malloc 而不释放的话,那么就会产生堆溢出,爆堆。

3.2 堆栈大小和栈溢出

关于堆栈的大小,Linux下有个指令可以查看,一般情况下为8-10M。当局部变量大小大于这个数值或者递归层数过多时,进行发生栈溢出。

ulimit -a# ulimit -s //可直接查看堆栈大小

这里显示栈大小8M,可以用程序测试一下,栈的大小到底是否是这么大。测试程序参考 linux下栈空间大小(ulimit):

#include <stdio.h>
#include <stdlib.h>void test(int i)
{char temp[1024*1024] = {0};printf("%s %d num = %d!\r\n", __FUNCTION__, __LINE__, ++i);test(i);
}int main(void)
{test(0);return 0;
}

测试结果确并未如我上面参考的那个博主的一样,他得出Linux下主线程栈大小比子线程多大概2M的样子,可是我的测试结果都是一样(至少在M级是一样),结果如下:

结果证实了此前查询得出的栈大小为8M 这个事实(因为还有参数传递,和局部变量,所以是肯定到达不了8的)。为了知道我计算机的实际栈大小,以及后续的证实,进行了手动二分来确定栈具体大小(有点傻。。)

理论上堆栈空间8M=8*1024*1024 = 2*1024*1024 = 2097152 个int

还有 .bss区大小的问题没有测试,未完待续,有时间再补充吧。。

全局变量和静态变量以及内存堆栈的关系相关推荐

  1. 深入理解C语言系列之内存和地址的故事(虚拟内存分区、全局变量与静态变量、外部函数内部函数、选择性编译)

    文章目录 一.内存的分区 二.虚拟内存分区 三.变量作用域与静态变量 四.外部函数与内部函数 五.include与define选择性编译 一.内存的分区 1.内存分为:物理内存和虚拟内存. 物理内存︰ ...

  2. python中静态变量的作用_小白必读文章之全局变量与静态变量

    全局变量与静态变量 static 声明的变量在C语言中有两方面的特征: 1.变量被放在程序的全局存储区中,这样在下一次调用的时候还可以保持原来的赋值.这一点是它与堆栈变量和堆变量的区别. 2.变量用s ...

  3. 全局变量、局部变量、静态全局变量、静态局部变量在内存里的区别(转)

    转:http://blog.163.com/zhangkai-@126/blog/static/312636552011101510416242/ 一.程序的内存分配 一个由C/C++编译的程序占用的 ...

  4. java 静态全局变量_静态变量static和全局变量global

    静态变量static , 全局变量global 静态变量 在java也叫类变量从名字可以看出它是属于某个类的而不是类的实例.它的关键字是static存储在静态存储区,当程序执行,类的代码被加载到内存, ...

  5. c++全局变量与静态变量

    概述: 全局变量和和由static修饰的静态变量都被储存在全局数据区.全局数据区的内存在程序运行时会被全部置'0'.这不同于局部变量,局部变量在栈上分配内存,但此块内存一般不为零,且编译器不会在局部变 ...

  6. 【C++】局部变量、全局变量、静态变量与动态对象的性质

    [fishing-pan:https://blog.csdn.net/u013921430转载请注明出处] 概述 局部变量 在一个函数内部定义的变量(包括函数形参)是局部变量. 全局变量 在函数外定义 ...

  7. 详解全局变量,全局变量与静态变量的区别

    特点: ① 作用域:全局可见.        全局变量(外部变量)是在函数外部定义的,它的作用域为从变量的定义处开始,到本程序文件的末尾.        注:通常把超出一个函数的作用域称为全局作用域, ...

  8. 局部变量、全局变量、静态变量

    局部变量 定义:局部变量指在程序中只在特定过程或函数中可以访问的变量.换言之,在一个函数内部定义的变量是内部变量,它只在本函数范围内有效,也就是说只有在本函数内才能使用它们,在此函数以外时不能使用这些 ...

  9. react-native全局变量和静态变量使用

    react-native 多个类引入变量,可以使用下面三个方式 静态变量 全局变量的使用: 1 导入文件方式 2 全局变量方式 实现类 Test.js import {Button, Text, Vi ...

最新文章

  1. iceberg问题小结
  2. Mycat实现读写分离
  3. VIM 命令使用大全
  4. 几个值得收藏的国外有关Vue.js网站
  5. PostgreSQL 8.3 以上的中文全文索引使用介绍
  6. 浅析无字符数字构造webshell
  7. linux文件的打包与下载总结,linux下文件的打包和压缩
  8. Nginx源码安装,配置开机自启
  9. 在mac 上安装 mpkg
  10. 相对湿度与绝对湿度转换表包含负温度
  11. chrome主页被修改(Google Chrome主页被hao123劫持解决办法)
  12. 新教育杂志新教育杂志社新教育编辑部2023年第6期目录
  13. 概率论基础 —— 3.离散型、连续型概率模型,及其概率密度与概率分布函数
  14. Android热更新,android组件化通信
  15. python -- 字符串练习题
  16. 数据包结构(IVI,NID,CTL,TTL,SEQ,SRC,DST,TransPDU,NetMIC)
  17. Qt文件QFile 和文件夹QDir
  18. @WebFilter不拦截 action
  19. MTK平台Modem(2G、3G、4G)配置之编译环境搭建
  20. 腾讯云服务器配置https 部署安装ssl证书

热门文章

  1. YOLO系列目标检测算法详解
  2. 《Tomcat内核设计剖析》勘误表
  3. 三个变量存在一个协整方程_计量经济学31个简答参考答案
  4. 数据结构(十六)——左高树(含合并过程详细图解)
  5. Acwing:COW(DP+状态机 Python)
  6. 谷歌卫星地图下载器bigemap的优势
  7. [收藏]《观察与思考》:相信中国,寻找下一个比尔·盖茨
  8. 一大早,是什么让技术群发出强人锁男、男上加男、勉为骑男?
  9. 运维(39) 通过KubeSphere部署SpringBoot到K8S案例 DevOps
  10. 【人工智能】八数码问题:广度搜索、深度搜索