1. 堆和栈的区别
- 堆栈空间分配不同。 栈由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等;堆一般由程序员分配释放。
- 堆栈缓存方式不同。 栈使用的是一级缓存, 它们通常都是被调用时处于存储空间中,调用完毕立即释放;堆则是存放在二级缓存中,速度要慢些。
- 堆栈数据结构不同。堆类似数组结构;栈类似栈结构,先进后出。
2. 在C++中,内存分成5个区
分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。
- 栈,在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。
- 堆,就是那些由new分配的内存块,一般一个new就要对应一个delete。
- 自由存储区,就是那些由malloc等分配的内存块,和堆是十分相似的,不过是用free来结束自己的生命。
- 全局/静态存储区,全局变量和静态变量被分配到同一块内存中。
- 常量存储区,这是一块比较特殊的存储区,里面存放的是常量,不允许修改。
3. 程序的section区
数据段: 存放程序中已初始化的全局变量和静态变量的一块内存区域。
代码段: 存放程序执行代码的一块内存区域。只读,代码段的头部还会包含一些只读的常数变量。
BSS 段: 存放程序中未初始化的全局变量和静态变量的一块内存区域。
堆区: 动态申请内存用。堆从低地址向高地址增长。
栈区: 存储局部变量、函数参数值。栈从高地址向低地址增长。是一块连续的空间。
最后还有一个文件映射区,位于堆和栈之间。
4. 程序启动的过程
- 操作系统首先创建相应的进程并分配私有的进程空间,然后操作系统的加载器负责把可执行文件的数据段和代码段映射到进程的虚拟内存空间中。
- 加载器读入可执行程序的导入符号表,根据这些符号表可以查找出该可执行程序的所有依赖的动态链接库。
- 加载器针对该程序的每一个动态链接库调用LoadLibrary
(1)查找对应的动态库文件,加载器为该动态链接库确定一个合适的基地址。
(2)加载器读取该动态链接库的导入符号表和导出符号表,比较应用程序要求的导入符号是否匹配该库的导出符号。
(3)针对该库的导入符号表,查找对应的依赖的动态链接库,如有跳转,则跳到3。
(4)调用该动态链接库的初始化函数。 - 初始化应用程序的全局变量,对于全局对象自动调用构造函数。
- 进入应用程序入口点函数开始执行。
怎么判断数据分配在栈上还是堆上:首先局部变量分配在栈上;而通过malloc和new申请的空间是在堆上。
BSS段通常是指用来存放程序中未初始化的或者初始化为0的全局变量和静态变量的一块内存区域。特点是可读写的,在程序执行之前BSS段会自动清0。
5. 内存对齐
内存对齐应用于三种数据类型中:struct/class/union
struct/class/union内存对齐原则有四个:
数据成员对齐规则:结构(struct)或联合(union)的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小的整数倍开始。
结构体作为成员:如果一个结构体里有某些结构体成员,则结构体成员要从其内部"最宽基本类型成员"的整数倍地址开始存储。
收尾工作:结构体的总大小,也就是sizeof的结果,必须是其内部最大成员的"最宽基本类型成员"的整数倍。不足的要补齐。
sizeof(union),以结构里面size最大元素为union的size,因为在某一时刻,union只有一个成员真正存储于该地址。