堆和栈的区别?,堆和栈的理解
以下内容转自http://blog..net/hairetz/article/details/4141043.
一,程序的初步知识记忆分配
C/C编译程序占用的内存分为以下几部分
1.stack)——由编译器自动分配和释放,它存储函数的参数值、局部变量的值等。那
该操作类似于数据结构中的堆栈。
2.heap)——一般由程序员分配和释放。如果程序员不释放它,操作系统可能会在程序结束时返回它。
收到。注意在数据结构上和堆不同,但是分配方式和链表差不多,呵呵。
3.全局区域(静态区域)-全局变量和静态变量存储在一起并被初始化。
全局变量和静态变量在一个区域,未初始化的全局变量和未初始化的静态变量在相邻的区域。
一个区域。-程序完成后由系统释放。
4.文本常量区域-常量字符串位于此处。程序完成后,由系统释放。
5.程序代码区——存储函数体的二进制代码。
第二,示例程序
这是一位前辈写的,写的很详细。
//main.cpp
int a=0;全局初始化区
char * p1全局未初始化区域
主()
{
int b;棚
char s[]= ABC ;棚
char * p2棚
char * p3= 12345623456/0在常量区,p3在堆栈上。
静态int c=0;全局(静态)初始化区
P1=(char *)malloc(10);
p2=(char *)malloc(20);
10和20字节的分配区域在堆区域。
strcpy(p1, 123456 );23456/0放在常量区,编译器可能会将其与p3指向的‘123456’进行比较。
优化到一个地方。
}
二、堆和栈的理论知识
2.1应用方法
堆栈:
由系统自动分配。比如在函数中声明一个局部变量int b;系统自动在栈中为B打开一个空的空间
间距
堆:
需要程序员自己申请,并在c中注明malloc函数的大小。
P1=(char *)马洛克(10);
在c中使用new运算符。
P2=新字符[10];
但是请注意,p1和p2本身就在堆栈中。
2.2
应用后系统的响应
堆栈:只要堆栈剩余空间大于请求空间,系统就会为程序提供内存,否则会报告异常提示堆栈溢出。
出去。
Heap:首先你要知道操作系统有一个空闲内存地址的链表。当系统接收到程序的应用时,
遍历链表,查找其空间大于应用空间的第一个堆节点,然后从空闲节点列表中列出该节点。
删除,并将该节点的空间分配给程序。此外,对于大多数系统,它将在这个内存空间中
在第一个地址记录这个分配的大小,以便代码中的delete语句可以正确地释放这个内存空间。
此外,因为找到的堆节点的大小不一定完全等于应用程序的大小,所以系统会自动发送冗余的那个。
把它放回自由链表。
2.3应用规模的限制
堆栈:在Windows下,堆栈是一种扩展到低位地址的数据结构,是连续内存的一个区域。这句话的意思
但是堆栈顶部的地址和堆栈的最大容量是由系统预先指定的。在WINDOWS下,堆栈的大小是2M(也有
说是1M,简而言之就是编译时确定的常数)。如果应用的空间超过堆栈的剩余空间,它将
提示溢出。因此,堆栈中的可用空间很小。
Heap: Heap是扩展到高位地址的数据结构,是一个不连续的内存区域。这是因为系统使用链表来存储。
空闲内存地址自然是不连续的,链表的遍历方向是从低位地址到高位地址。堆的大小
受到计算机系统中可用虚拟内存的限制。可见堆获得的空间更灵活,更大。
2.4应用效率比较:
堆栈由系统自动分配,速度更快。但是程序员控制不了。
Heap是new分配的内存,一般比较慢,容易出现内存碎片,但是用起来最方便。
另外,在WINDOWS下,最好的方法是使用VirtualAlloc来分配内存。他不在堆里,也不在栈里。
在直接进程的地址空间里保留一块内存,虽然用起来最不方便。但它速度快,最灵活。
2.5堆和堆栈中的存储内容
栈:当一个函数被调用时,栈上的第一条是主函数中的下一条指令(函数调用语句中的下一条指令可以
执行语句的地址),然后是函数的参数。在大多数C编译器中,参数是从右向左堆叠的。
然后是函数中的局部变量。请注意,静态变量是不堆叠的。
当这个函数调用完成后,先将局部变量弹出堆栈,然后是参数,最后堆栈顶部的指针指向它们开始时存储的位置。
地址,即主函数中的下一条指令,程序从这里继续运行。
堆:通常,在堆的头部使用一个字节来存储堆的大小。堆的具体内容由程序员安排。
2.6访问效率比较
char S1[]= aaaaaaaaaaaaaaaa ;
char * s2= bbbbbbbbbbbbbbbbb
aaaaaaaaaa是在运行时分配的;
Bbbbbbbbbbb是在编译时确定的;
但是在以后的访问中,栈上的数组比指针指向的字符串(比如heap)要快。
例如:
#包括
void main()
{
char a=1;
char c[]= 1234567890 ;
char * p= 1234567890
a=c[1];
a=p[1];
返回;
}
相应的装配代码
10:a=c[1];
00401067 8A 4D F1 mov cl,字节指针[ebp-0Fh]
0040106A 88 4D FC mov字节ptr [ebp-4],cl
11:a=p[1];
0040106D 8B 55 EC mov edx,dword ptr [ebp-14h]
00401070 8A 42 01 mov al,字节ptr [edx 1]
00401073 88 45 FC mov字节ptr [ebp-4],al
第一个将字符串中的元素直接读入寄存器cl,而第二个首先读取指针值。
在edx中,根据edx读取字符明显很慢。
2.7总结:
堆和栈的区别可以通过下面的比喻看出:
使用栈就像在餐厅吃饭一样,只需要点餐(发出申请)、付款、吃饭(使用)。当你吃饱了,就
去,不讲究切菜、洗菜等准备工作和洗碗、刷锅等收尾工作,他的优点是快,但既然
通过小的程度。
就像自己做自己喜欢的菜一样。很麻烦,但是很适合自己的口味,而且很自由。
度。(经典!)