在学习之前我们先看看ELF文件。
ELF分为三种类型:.o 可重定位文件(relocalble file),可执行文件以及共享库(shared library),三种格式基本上从结构上是一样的,只是具体到每一个结构不同。Segment实际上就是由section组成的,将相应的一些section映射到一起就叫segment了,就是说segment是由0个或多个section组成的,实际上本质都是section。在这里我们首先来仔细了解一下section和segment的概念:section就是相同或者相似信息的集合,比如我们比较熟悉的.text .data .bss section,.text是可执行指令的集合,.data是初始化后数据的集合,.bss是未初始化数据的集合。实际上我们也可以将一个程序的所有内容都放在一起,就像dos一样,但是将可执行程序分成多个section是很有好处的,比如说我们可以将.text section放在memory的只读空间内,将可变的.data section放在memory的可写空间内。
从可执行文件的角度来讲,如果一个数据未被初始化那就不需要为其分配空间,所以.data和.bss一个重要的区别就是.bss并不占用可执行文件的大小,它只是记载需要多少空间来存储这些未初始化数据,而不分配实际的空间。
1、一般情况下,一个可执行二进制程序在存储(没有调入到内存运行)时拥有3个部分,分别是代码段(code segment/text segment)、数据段(data)和BSS段。这3个部分一起组成了该可执行程序的文件。
★★可执行二进制程序 = 代码段(text)+数据段(data)+BSS段★★
2、而当程序被加载到内存单元时,则需要另外两个域:堆域和栈域。
★★正在运行的C程序 = 代码段+初始化数据段(data)+未初始化数据段(BSS)+堆+栈★★
3、在将应用程序加载到内存空间执行时,操作系统负责代码段、数据段和BSS段的加载,并将在内存中为这些段分配空间。栈亦由操作系统分配和管理,堆段由程序员自己管理,即显示地申请和释放空间。
4、动态分配与静态分配,二者最大的区别在于:1. 直到Run-Time的时候,执行动态分配;而在compile-time的时候,就已经决定好了分配多少Text+Data+BSS+Stack。
数据段:data(初始化值不为0)包含静态初始化的数据,所以有初值的全局变量和static变量在data区。数据段属于静态内存分配。
bss段:Block Started by Symbol的简称,通常是指用来存放程序中未初始化的全局变量的一块内存区域,在程序载入时由内核清0。BSS段属于静态内存分配。
★★★★注意静态变量初始化为零和全局静态变量初始化为零的情况,都是存储在bss段★★★★
初始化的静态局部变量但是却属于bss段,为什么?初始化为零,这和没有初始化,默认是零的情况一样,都存储在bss段,如果初始化为其他的值,就会存储在data段。
const int g_A = 10; //代码段
int g_B = 20; //数据段
static int g_C = 30; //数据段
static int g_D; //BSS段
int g_E; //BSS段
char *p1; //BSS段
void main( ) {
static int local_C = 0; //数据段
static int local_D; //数据段
char *p3 = "123456"; //123456在代码段,p3在栈上
strcpy( p1, "123456" ); //123456放在常量区,编译器可能会将它与p3所指向 的"123456"优化成一块
在C++中,内存分成5个区,堆、栈、自由存储区、全局/静态存储区和常量存储区。
堆,malloc在堆上分配的内存块,使用free释放内存。
自由存储区,new所申请的内存则是在自由存储区上,使用delete来释放。
全局/静态存储区,全局变量和静态变量被分配到同一块内存中,在以前的C语言中,全局变量又分为初始化的和未初始化的,在C++里面没有这个区分了,他们共同占用同一块内存区。
常量存储区,这是一块比较特殊的存储区,他们里面存放的是常量,不允许修改。
自由存储区与堆的区别
自由存储是C++中通过new与delete动态分配和释放对象的抽象概念,而堆(heap)是C语言和操作系统的术语,是操作系统维护的一块动态分配内存。
new所申请的内存区域在C++中称为自由存储区。藉由堆实现的自由存储,可以说new所申请的内存区域在堆上。
堆与自由存储区还是有区别的,它们并非等价。