orisun@orisun-desktop:~/Program$size memory2
text data bss dec hexfilename
2074 284 16 2374 946memory2
可以看到一个可执行程序在存储(没有调入内存)时分为代码区,数据区,未初始化数据区三部分。
(1)代码区存放CPU执行的机器指令。通常代码区是共享的,即其它执行程序可调用它。
(2)数据区存放已初始化的全局变量,静态变量(包括全局和局部的),常量。static全局变量和static函数只能在当前文件中被调用。
(3)未初始化数据区(uninitializeddata segment,BSS)存放全局未初始化的变量。BSS的数据在程序开始执行之前被初始化为0或NULL。
代码区所在的地址空间最低,往上依次是数据区和BSS区,并且数据区和BSS区在内存中是紧挨着的。
可执行程序在运行时又多出了两个区域:栈区和堆区。
(4)栈区。由编译器自动释放,存放函数的参数值,局部变量等。每当一个函数被调用时,该函数的返回类型和一些调用的信息被存储到栈中。然后这个被调用的函数再为它的自动变量和临时变量在栈上分配空间。每调用一个函数一个新的栈就会被使用。栈区是从高地址位向低地址位增长的,是一块连续的内在区域,最大容量是由系统预先定义好的,申请的栈空间超过这个界限时会提示溢出,用户能从栈中获取的空间较小。
(5)堆区。用于动态内存分配,位于BSS和栈中间的地址位。由程序员申请分配(malloc)和释放(free)。堆是从低地址位向高地址位增长,采用链式存储结构。频繁地malloc/free造成内存空间的不连续,产生碎片。当申请堆空间时库函数按照一定的算法搜索可用的足够大的空间。因此堆的效率比栈要低的多。
举个例子说明各种变量存放在什么区:
int a=0; //a在全局已初始化数据区
char *p1; //p1在BSS区(未初始化全局变量)
main()
{
int b; //b为局部变量,在栈区
char s[]="abd"; //s为局部数组变量,在栈区
//"abc"为字符串常量,存储在已初始化数据区
char *p1,*p2; //p1,p2为局部变量,在栈区
char *p3="123456"; //p3在栈区,1234560在已初始化数据区
static int c=0; //c为局部(静态)数据,在已初始化数据区
//静态局部变量会自动初始化(因为BSS区自动用0或NULL初始化)
p1=(char*)malloc(10); //分配得来的10个字节的区域在堆区
p2=(char*)malloc(20); //分配得来的20个字节的区域在堆区
free(p1);
free(p2);
p1=NULL; //显示地将p1置为NULL,避免以后错误地使用p1
p2=NULL;
}