整理:
一、存储空间的划分
一个由C/C++编译的程序占用的内存分为以下几个部分:
1、栈区(stack)— 由编译器自动分配释放,存放函数的参数值,局部变量的值等。其
操作方式类似于数据结构中的栈。
2、堆区(heap)— 一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回
收。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。
3、全局区、静态区(static)— 全局变量和静态变量的存储是放在一块的,初始化的
全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另
一块区域。程序结束后由系统释放。
4、文字常量区 — 存放常量字符串。程序结束后由系统释放。
5、程序代码区—存放函数体的二进制代码。
二.堆与栈的区别
区别:
1、管理方式不同;
栈:编译器自动管理,不用释放。
堆:创建,释放工作由程序员控制。
2、空间大小不同;
栈:空间较小,默认空间1M或者2M,可以手动修改编译器增加栈大小,但是会产生增加内存开销,延长启动时间等问题。
堆:32位系统,堆内存可达到4G空间,大小受计算机中有效的虚拟内存限制。
3、能否产生碎片不同;
栈:先进先出队列,存储区是一块连续的内存区域,不会产生碎片。
堆:频繁的使用new/delete会造成内存空间的不连续,从而造成大量的碎片。
4、生长方向不同;
栈:生长方向向下,即向低位寻址,向着内存地址减小的方向增长。
堆:生长方向向上,即向高位寻址,向着内存地址增加的方向增长。
5、分配方式不同;
栈:有静态分配,动态分配两种,静态分配如局部变量,动态分配由alloca函数进行分配,分配之后都是由编译器进行释放,无需手动释放。
堆:动态分配,需要手动申请,手动释放,如malloc/free,new/delete。
6、分配效率不同;
栈:效率较高,栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行。
堆:效率较低,堆是C/C++函数库提供的,它的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会分到足够大小的内存,然后进行返回。
三.对齐原则
《Windows核心编程》:当CPU访问正确对齐的数据时,它的运行效率最高,当数据大小的数据模数的内存地址是0时,数据是对齐的。例如:WORD值应该是总是从被2除尽的地址开始,而DWORD值应该总是从被4除尽的地址开始,数据对齐不是内存结构的一部分,而是CPU结构的一部分。当CPU试图读取的数值没有正确的对齐时,CPU可以执行两种操作之一:产生一个异常条件;执行多次对齐的内存访问,以便读取完整的未对齐数据,若多次执行内存访问,应用程序的运行速度就会慢。在最好的情况下,是两倍的时间,有时更长。
关于结构体内存对齐(在没有#pragma pack宏的情况下) :
•原则1
数据成员对齐规则:结构(struct或联合union)的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储)。
•原则2
结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储。(struct a里存有struct b,b里有char,int,double等元素,那b应该从8的整数倍开始存储。)
•原则3
收尾工作:结构体的总大小,也就是sizeof的结果,必须是其内部最大成员的整数倍,不足的要补齐。
部分内容参考自博文:
http://blog.csdn.net/doniexun/article/details/38294935
http://blog.csdn.net/dapengbusi/article/details/49070107