如下内容,大部分整理自网络html
C分为四个区:堆,栈,静态全局变量区,常量区linux
C++内存分为5个区域(堆栈全常代 ):c++
堆 heap :
由new分配的内存块,其释放编译器不去管,由咱们程序本身控制(一个new对应一个delete)。若是程序员没有释放掉,在程序结束时OS会自动回收。涉及的问题:“缓冲区溢出”、“内存泄露”程序员
栈 stack :
是那些编译器在须要时分配,在不须要时自动清除的存储区。存放局部变量、函数参数。
存放在栈中的数据只在当前函数及下一层函数中有效,一旦函数返回了,这些数据也就自动释放了。数组
全局/静态存储区 (.bss段和.data段) :
全局和静态变量被分配到同一块内存中。在C语言中,未初始化的放在.bss段中,初始化的放在.data段中;在C++里则不区分了。网络
常量存储区 (.rodata段) :
存放常量,不容许修改(经过非正当手段也能够修改)数据结构
代码区 (.text段) :
存放代码(如函数),不容许修改(相似常量存储区),但能够执行(不一样于常量存储区)架构
根据c/c++对象生命周期不一样,c/c++的内存模型有三种不一样的内存区域,即框架
而代码虽然占内存,但不属于c/c++内存模型的一部分函数
在linux系统中,程序在内存中的分布以下所示:
低地址
.text---> .data --->.bss
--->heap(堆) --> unused <-- stack(栈)
-->env
高地址
其中 :
.text 部分是编译后程序的主体,也就是程序的机器指令。
.data 和 .bss 保存了程序的全局变量,.data保存有初始化的全局变量,.bss保存只有声明没有初始化的全局变量。
heap(堆)中保存程序中动态分配的内存,好比C的malloc申请的内存,或者C++中new申请的内存。堆向高地址方向增加。
stack(栈)用来进行函数调用,保存函数参数,临时变量,返回地址等。
BSS 是“Block Started by Symbol”的缩写,意为“以符号开始的块”。BSS是Unix连接器产生的未初始化数据段。其余的段分别是包含程序代码的 “text”段和包含已初始化数据的“data”段。BSS段的变量只有名称和大小却没有值。此名后来被许多文件格式使用,包括PE。“以符号开始的块” 指的是编译器处理未初始化数据的地方。BSS节不包含任何数据,只是简单的维护开始和结束的地址,以便内存区能在运行时被有效地清零。BSS节在应用程序 的二进制映象文件中并不存在。
在采用段式内存管理的架构中(好比intel的80x86系统),bss段(Block Started by Symbol segment)一般是指用来存放程序中未初始化的全局变量的一块内存区域,通常在初始化时bss 段部分将会清零。bss段属于静态内存分配,即程序一开始就将其清零了。
好比,在C语言之类的程序编译完成以后,已初始化的全局变量保存在.data 段中,未初始化的全局变量保存在.bss 段中。
text和data段都在可执行文件中(在嵌入式系统里通常是固化在镜像文件中),由系 统从可执行文件中加载;而bss段不在可执行文件中,由系统初始化。
一个正在运行着的C编译程序占用的内存分为代码区、初始化数据区、未初始化数据区、堆区 和栈区5个部分。
(1)代码区(text segment)。代码区指令根据程序设计流程依次执行,对于顺序指令,则只会执行一次(每一个进程),若是反复,则须要使用跳转指令,若是进行递归,则需 要借助栈来实现。
代码区的指令中包括操做码和要操做的对象(或对象地址引用)。若是是当即数(即具体的数值,如5),将直接包含在代码中;若是是局部数据,将在栈区 分配空间,而后引用该数据地址;若是是BSS区和数据区,在代码中一样将引用该数据地址。
(2)全局初始化数据区/静态数据区(Data Segment)。只初始化一次。
(3)未初始化数据区(BSS)。在运行时改变其值。
(4)栈区(stack)。由编译器自动分配释放,存放函数的参数值、局部变量的值等。其操做方式相似于数据结构中的栈。每当一个函数被调用,该函 数返回地址和一些关于调用的信息,好比某些寄存器的内容,被存储到栈区。而后这个被调用的函数再为它的自动变量和临时变量在栈区上分配空间,这就是C实现 函数递归调用的方法。每执行一次递归函数调用,一个新的栈框架就会被使用,这样这个新实例栈里的变量就不会和该函数的另外一个实例栈里面的变量混淆。
(5)堆区(heap)。用于动态内存分配。堆在内存中位于bss区和栈区之间。通常由程序员分配和释放,若程序员不释放,程序结束时有可能由OS 回收。
之因此分红这么多个区域,主要基于如下考虑:
一个进程在运行过程当中,代码是根据流程依次执行的,只须要访问一次,固然跳转和递归有可能使代码执行屡次,而数据通常都须要访问屡次,所以单独开辟 空间以方便访问和节约空间。
临时数据及须要再次使用的代码在运行时放入栈区中,生命周期短。
全局数据和静态数据有可能在整个程序执行过程当中都须要访问,所以单独存储管理。
堆区由用户自由分配,以便管理。
下面经过一段简单的代码来查看C程序执行时的内存分配状况。相关数据在运行时的位置如注释所述。
//main.cpp int a = 0; //a在全局已初始化数据区 char *p1; //p1在BSS区(未初始化全局变量) main() { int b; //b在栈区 char s[] = "abc"; //s为数组变量,存储在栈区, //"abc"为字符串常量,存储在已初始化数据区 char *p1,*p2; //p一、p2在栈区 char *p3 = "123456"; //123456\0在已初始化数据区,p3在栈区 static int c =0; //C为全局(静态)数据,存在于已初始化数据区 //另外,静态数据会自动初始化 p1 = (char *)malloc(10);//分配得来的10个字节的区域在堆区 p2 = (char *)malloc(20);//分配得来的20个字节的区域在堆区 free(p1); free(p2); }