

内存四区
总的来说内存可以分为四个区域:静态存储区和动态存储区(又分为栈区和堆区)和代码区。
其中
- 全局(静态)存储区分为三段: data 、bss、rodata 段。存储在静态数据区的变量会在程序刚开始运行时就完成初始化,也是唯一的一次初始化。
- data 段(全局初始化区)存放初始化的全局变量和静态变量
- bss 段(全局未初始化区)存放未初始化的全局变量和静态变量,区别初始化和非初始化是为了空间效率。未初始化变量不占据实际内存空间(bss变量只在段表中记录大小,在符号表中记录符号。当文件加载运行时,才分配空间以及初始化),BBS段在程序执行之前会被系统自动清0,所以未初始化的全局变量和静态变量在程序执行之前已经为0。(也正是因为反正在bss上的变量肯定都是0,所以不需要为他们分配空间)
- rodata 段,常量区,用于存放各类常量,如:const、字面量、#define
特别注意下面的这个例子:
int main()
{
char s[] = "abc"; //栈
char *p = "123456"; //123456\0在常量区,p在栈上。
}
由于两者都是局部变量,所以都是动态存储区内的变量。
char s[]的含义是一个char类型的数组,只是缺省了长度,这个长度将由编译器以赋值的内容来推断。所以这句话相当于char s[4] = "abc",所以是在栈上的。
char *p是一个char类型的指针变量,这个指针指向了一个常量的字符串。常量在静态存储区的rodata段。而指针变量因为其是局部变量所以是在栈上的。
堆和栈的区别可以总结为以下的六个方面
管理方式不同
堆:由程序员分配释放,若程序员不释放,程序结束时可能由OS回收
栈:由操作系统自动分配释放
碎片问题
堆:是不连续的内存区域,频繁的new/malloc会造成大量的内存碎片
栈:是一块连续的内存的区域,先入后出的结构,进出一一对应,不会产生内存碎片。
空间大小不同
堆是不连续的内存空间,数据结构是链表,空间大。
栈和数据结构中的栈一样,是一块连续的内存空间,空间小。通常为2M
分配方式不同
堆是动态分配,没有静态分配。当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序
栈中有静态分配也有动态分配,静态分配是由编译器完成,动态分配由alloca函数分配,编译器自动释放,无需程序员实现。
存放内容不同
栈:存放函数的参数值(从右往左入栈),局部变量(非静态)、函数返回地址等值
堆:比较灵活,由程序员安排
申请效率不同
栈由系统自动分配,速度较快。 堆是由new分配的内存,需要查找足够大的内存大小,一般速度比较慢。