【c基础知识】内存分区

来源:互联网 发布:java 邮箱匹配 编辑:程序博客网 时间:2024/04/24 12:57

首先我们来了解一下什么是数据类型?为什么需要数据类型?

数据类型是为了更好进行内存的管理,让编译器能确定分配多少内存。

数据类型基本概念:

Ø 类型是对数据的抽象;

Ø 类型相同的数据具有相同的表示形式、存储格式以及相关操作;

Ø 程序中所有的数据都必定属于某种数据类型;

Ø 数据类型可以理解为创建变量的模具:固定大小内存的别名;


这里特别要提一下void类型

void字面意思是”无类型”,void* 无类型指针,无类型指针可以指向任何类型的数据。

void定义变量是没有任何意义的,当你定义void a,编译器会报错。

void真正用在以下两个方面:

Ø 对函数返回的限定;

Ø 对函数参数的限定;

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

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

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

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

4)链接:将目标文件链接为可执行程序

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


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

l 代码区

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

 

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

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

 

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

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

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

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

栈区

由系统进行内存的管理。主要存放函数的参数以及局部变量。在函数完成执行,系统自行释放栈区内存,不需要用户管理。

堆区

由编程人员手动申请,手动释放,若不手动释放,程序结束后由系统回收,生命周期是整个程序运行期间。使用malloc或者new进行堆的申请

全局/静态区

全局静态区内的变量在编译阶段已经分配好内存空间并初始化这块内存在程序运行期间一直存在,它主要存储全局变量静态变量常量


总结:

在理解C/C++内存分区时,常会碰到如下术语:数据区,堆,栈,静态区,常量区,全局区,字符串常量区,文字常量区,代码区等等,初学者被搞得云里雾里。在这里,尝试捋清楚以上分区的关系。

数据区:堆,栈,全局/静态存储区。
全局/静态存储区:常量区,全局区静态区。
常量区:字符串常量区常变量区。
代码区:存放程序编译后的二进制代码,不可寻址区。

可以说,C/C++内存分区其实只有两个,即代码区和数据区。


原创粉丝点击