开发者社区> 流楚丶格念> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

程序内存分区

简介: 程序内存分区
+关注继续查看

内存分区


程序运行之前


我们要想执行我们编写的c程序,那么第一步需要对这个程序进行编译。


  1. 预处理:宏定义展开、头文件展开、条件编译,这里并不会检查语法


  1. 编译:检查语法,将预处理后文件编译生成汇编文件


  1. 汇编:将汇编文件生成目标文件(二进制文件)


  1. 链接:将目标文件链接为可执行程序


当我们编译完成生成可执行文件之后,我们通过在linux下size命令可以查看一个可执行二进制文件基本情况:


image


通过上图可以得知,在没有运行程序前,也就是说程序没有加载到内存前,可执行程序内部已经分好3段信息,分别为代码区(text)、数据区(data) 和 未初始化数据区(bss) 3 个部分(有些人直接把data和bss合起来叫做静态区或全局区)。


代码区


存放 CPU 执行的机器指令。


通常代码区是可共享的(即另外的执行程序可以调用它),使其可共享的目的是对于频繁被执行的程序,只需要在内存中有一份代码即可。代码区通常是只读的,使其只读的原因是防止程序意外地修改了它的指t令。另外,代码区还规划了局部变量的相关信息。


全局初始化数据区/静态数据区(data段)


该区包含了在程序中明确被初始化的全局变量、已经初始化的静态变量(包括全局静态变量和t)和常量数据(如字符串常量)。


未初始化数据区(又叫 bss 区)


存入的是全局未初始化变量和未初始化静态变量。未初始化数据区的数据在程序开始执行之前被内核初始化为 0 或者空(NULL)。


总体来讲说,程序源代码被编译之后主要分成两种段:程序指令(代码区)和程序数据(数据区)。代码段属于程序指令,而数据域段和.bss段属于程序数据。


问题:那为什么把程序的指令和程序数据分开呢?


  • 程序被load到内存中之后,可以将数据和代码分别映射到两个内存区域。由于数据区域对进程来说是可读可写的,而指令区域对程序来讲说是只读的,所以分区之后呢,可以将程序指令区域和数据区域分别设置成可读可写或只读。这样可以防止程序的指令有意或者无意被修改;


  • 当系统中运行着多个同样的程序的时候,这些程序执行的指令都是一样的,所以只需要内存中保存一份程序的指令就可以了,只是每一个程序运行中数据不一样而已,这样可以节省大量的内存。比如说之前的Windows Internet Explorer 7.0运行起来之后, 它需要占用112 844KB的内存,它的私有部分数据有大概15 944KB,也就是说有96 900KB空间是共享的,如果程序中运行了几百个这样的进程,可以想象共享的方法可以节省大量的内存。


程序运行之后


程序在加载到内存前,代码区和全局区(data和bss)的大小就是固定的,程序运行期间不能改变。然后,运行可执行程序,操作系统把物理硬盘程序load(加载)到内存,除了根据可执行程序的信息分出代码区(text)、数据区(data)和未初始化数据区(bss)之外,还额外增加了栈区、堆区。


代码区(text segment)


加载的是可执行文件代码段,所有的可执行代码都加载到代码区,这块内存是不可以在运行期间修改的。


未初始化数据区(BSS)


加载的是可执行文件BSS段,位置可以分开亦可以紧靠数据段,存储于数据段的数据(全局未初始化,静态未初始化数据)的生存周期为整个程序运行过程。


全局初始化数据区/静态数据区(data segment)


加载的是可执行文件数据段,存储于数据段(全局初始化,静态初始化数据,文字常量(只读))的数据的生存周期为整个程序运行过程。


栈区(stack)


栈是一种先进后出的内存结构,由编译器自动分配释放,存放函数的参数值、返回值、局部变量等。在程序运行过程中实时加载和释放,因此,局部变量的生存周期为申请到释放该段栈空间。


堆区(heap)


堆是一个大容器,它的容量要远远大于栈,但没有栈那样先进后出的顺序。用于动态内存分配。堆在内存中位于BSS区和栈区之间。一般由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收。


变量类型的作用域、生命周期与存储位置


image.png

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
程序员需要了解的硬核知识之内存(三)
我们都知道,计算机是处理数据的设备,而数据的主要存储位置就是磁盘和内存,并且对于程序员来讲,CPU 和内存是我们必须了解的两个物理结构,它是你通向高阶程序员很重要的桥梁,那么本篇文章我们就来介绍一下基本的内存知识。
5 0
Java程序运行时内存分析
Java内存分析还是搞不懂啊,望大神多多指教
1370 0
一个C/C++程序内存分配形式
一:一个C/C++程序编译之后在内存中一般分为五个部分 1. 程序代码区:程序代码区主要用来存放程序执行代码,包括类成员函数、全局函数、静态函数等其它函数的代码。
797 0
JAVA程序的内存分配
栈区 由编译器自动分配和释放,存放临时变量和函数参数值等 堆区 由程序员分配和释放,如果程序员不手动释放,则由GC或操作系统释放 代码区 存放函数体二进制代码 全局区 存放全局变量 静态区 ...
589 0
C++电话本程序
/* C++电话本程序 */ /* 1.可实现txt文件的读取和保存。 */ /* 2.可实现联系人的增添、删除和修改。 */ /* 3.可实现通过联系人查询号码。 */ /* 4.可实现通过号码查询联系人。 */ /* 5.可实现全部联系人的显示。 */ /* 运行环境vs2010||codebl
867 0
程序9
【程序9】  题目:一个数如果恰好等于它的因子之和,这个数就称为"完数"。例如6=1+2+3.编程找出1000以内的所有完数。 1 function addFactor1(num) { 2 var sum = 0; 3 ...
692 0
+关注
流楚丶格念
csdn平台优质创作者,51cto TOP博主,360图书馆科技博主,燕山大学目前大三在读,日拱一卒,功不唐捐,加油!!!
1010
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载