C/C++程序的内存分配

C/C++程序到内存分配

一个由C/C++编译到程序占用的内存(所有的描述讲的是程序在内存上的存储,而不是在磁盘上的存储)分为以下几个部分:

1、栈区(stack——由编译器自动分配释放,在不需要的时候自动清除。用于存放函数的参数、局部变量等。操作方式类似数据结构中的栈(后进先出)。

2、堆区(heap——一般由程序员分配释放,若程序员分配后不释放,程序结束后可能由OS回收。不同于数据结构中的堆,分配方式有些类似链表。

3全局区(静态区)——全局变量和静态变量存储在这里。程序结束后由系统释放。在以前到C语言中,全局变量又细分为初始化的数据段(DATA段)和未初始化的数据段(BSS段),在C++里已经没有这个区分了,它们共同占用同一块内存区。

4、常量存储区——常量字符串就存放在这里。一般不允许修改。程序结束后由系统释放。

5、代码区——存放函数体的二进制代码。

示意图如下:

|----------------------|    高地址
|    
栈区(Statk)   | -->向下增长
|----------------------|
|    
堆区(Heap)   | -->向上增长
|----------------------|
|
未初始化(BSS) |
|----------------------|
|  
初始化(Data)  |
|----------------------|
|   
常量存储区    |
|----------------------|

|   正文段(Text)   |
|----------------------|   
低地址

 

一、

代码段--textcode segment/text segment
text段在内存中被映射为只读,但.data.bss是可写的。
text段是程序代码段,在AT91库中是表示程序段的大小,它是由编译器在编译连接时自动计算的,当你在链接定位文件中将该符号放置在代码段后,那么该符号表示的值就是代码段大小,编译连接时,该符号所代表的值会自动代入到源程序中。

数据段--data
data包含静态初始化的数据,所以有初值的全局变量和static变量在data区。段的起始位置也是由连接定位文件所确定,大小在编译连接时自动分配,它和你的程序大小没有关系,但和程序使用到的全局变量,常量数量相关。数据段属于静态内存分配。 

bss--bss
bss是英文Block Started by Symbol(由符号开始的块)的简称,通常是指用来存放程序中未初始化的全局变量的一块内存区域,在程序载入时由内核清0BSS段属于静态内存分配。它的初始值也是由用户自己定义的连接定位文件所确定,用户应该将它定义在可读写的RAM区内,源程序中使用malloc分配的内存就是这一块,它不是根据data大小确定,主要由程序中同时分配内存最大值所确定,不过如果超出了范围,也就是分配失败,可以等空间释放之后再分配。BSS段属于静态内存分配。bss段的数据并不存放在磁盘上的程序文件中。原因是内核在程序开始前将他们都设置为0。

stack
(stack)保存函数的局部变量(但不包括static声明的变量, static 意味着在全局区(静态区)中存放变量),参数以及返回值。是一种后进先出Last In First OutLIFO)的数据结构,这意味着最后放到栈上的数据,将会是第一个从栈上移走的数据。对于哪些暂时存贮的信息,和不需要长时间保存的信息来说,LIFO这种数据结构非常理想。在调用函数或过程后,系统通常会清除栈上保存的局部变量、函数调用信息及其它的信息。栈另外一个重要的特征是,它的地址空间向下减少,即当栈上保存的数据越多,栈的地址就越低。栈(stack)的顶部在可读写的RAM区的最后。

heap:
(heap)保存函数内部动态分配内存,是另外一种用来保存程序信息的数据结构,更准确的说是保存程序的动态变量。堆是先进先出First In first OutFIFO)数据结构。它只允许在堆的一端插入数据,在另一端移走数据。堆的地址空间向上增加,即当堆上保存的数据越多,堆的地址就越高。

C/C++程序的内存分配

下图是APUE中的一个典型C内存空间分布图:

C/C++程序的内存分配

所以可以知道传入的参数,局部变量,都是在栈顶分布,随着子函数的增多而向下增长.
函数的调用地址(函数运行代码),全局变量,静态变量都是在分配内存的低部存在,malloc分配的堆则存在于这些内存之上,并向上生长.

.

站在汇编语言的角度,一个程序分为:
数据段 -- DS
堆栈段 -- SS
代码段 -- CS
扩展段 -- ES

站在高级语言的角度,根据APUE,一个程序分为如下段:
text
data (initialized)

bss

stack
heap

        1.一般情况下,一个可执行二进制程序(更确切的说,在Linux操作系统下为一个进程单元,在UC/OSII中被称为任务)在存储(没有调入到内存运行)时拥有3个部分,分别是代码段(text)、数据段(data)BSS段。这3个部分一起组成了该可执行程序的文件

★★可执行二进制程序代码段(text)+数据段(data)+未初始化数据段BSS★★

        2.而当程序被加载到内存单元时,则需要另外两个域:堆域和栈域。图1-1所示为可执行代码存储态运行态的结构对照图。一个正在运行的C程序占用的内存区域分为代码段、初始化数据段、未初始化数据段(BSS)、堆、栈5个部分。

★★正在运行的C程序 = 代码段+初始化数据段(data)+未初始化数据段(BSS)++★★

      3.在将应用程序加载到内存空间执行时,操作系统负责代码段、数据段和BSS段的加载,并将在内存中为这些段分配空间。栈亦由操作系统分配和管理,而不需要程序员显示地管理;堆段由程序员自己管理,即显示地申请和释放空间。

         4.动态分配与静态分配,二者最大的区别在于:1. 直到Run-Time的时候,执行动态分配,而在compile-time的时候,就已经决定好了分配多少Text+Data+BSS+Stack。2.通过malloc()动态分配的内存,需要程序员手工调用free()释放内存,否则容易导致内存泄露,而静态分配的内存则在进程执行结束后系统释放(Text,Data), 但Stack段中的数据很短暂,函数退出立即被销毁。

 C/C++程序的内存分配

 1-1从可执行文件a.out的角度来讲,如果一个数据未被初始化那就不需要为其分配空间,所以.data.bss一个重要的区别就是.bss并不占用可执行文件的大小,它只是记载需要多少空间来存储这些未初始化数据,而不分配实际的空间