rambo

栈与堆的区别

首先看一下动态分配的代码。

在程序会先确定在堆中分配内存的大小,然后调用 operator new 分配内存,然后返回这块内存的首地址,放入栈中。

补充知识

4个数据寄存器(EAX、EBX、ECX和EDX)
2个变址和指针寄存器(ESI和EDI)
2个指针寄存器(ESP和EBP)
eax:保存所有API函数的返回值。寄存器AX和AL通常称为累加(Accumulator),用累加器进行的操作可能需要更少时间。累加器可用于乘、除、输入/输出等操作,它们的使用频率很高;
ebx:基地址寄存器(Base Register)。它可作为存储器指针来使用;
ecx:称为计数寄存器(Count Register)。在循环和字符串操作时,要用它来控制循环次数;在位操作中,当移多位时,要用CL来指明移位的位数;
edx:称为数据寄存器(Data Register)。在进行乘、除运算时,它可作为默认的操作数参与运算,也可用于存放I/O的端口地址。

esp:栈指针寄存器(extended stack pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的栈顶。
ebp:基址指针寄存器(extended base pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的底部。

栈的默认大小是1MB。VS中选择 项目->属性->链接器->系统->堆栈保留大小,然后输入你想要的栈大小即可。

栈与堆的区别

碎片问题

在windows中,占用态的堆块被使用它的程序索引,而堆表只索引所有空闲态的堆块。重要的堆表有两种:空闲双向链表FreeList(空表) 和 快速单向链表Lookaside(快表)。对于堆来讲,频繁的 new/delete 势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。

对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出。

显然,堆的分配效率比栈要低得多。

生长方向:对于堆来讲,生长方向是向上的,也就是向着内存地址增加的方向,(用链表来存储的空闲内存地址的,而链表的遍历方向是由低地址向高地址);对于栈来讲,它的生长方向是向下的,是向着内存地址减小的方向增长。(定义一个栈底--这是高地址,每次压一个数据入栈,栈指针esp减去4(32位系统下),所以栈顶是向着内存低地址方向生长的。)