搜索
bottom↓
回复: 22

堆和栈有什么区别?至今还不明白【恢复】

[复制链接]

出0入0汤圆

发表于 2008-12-30 16:22:32 | 显示全部楼层 |阅读模式
能否详细说说??

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2008-12-31 15:54:33 | 显示全部楼层
好长啊  OMG~

出0入22汤圆

发表于 2008-12-31 15:47:46 | 显示全部楼层
很详细,谢谢。

出0入0汤圆

发表于 2008-12-31 15:12:10 | 显示全部楼层
【7楼】 lybwell 

积分:286

派别:

等级:------

来自:福建

 管道,是个变量呢,以后可以用到,现在不懂  

   



堆栈是"后入者先出",表现得像得柴堆,所以因此得名"栈".硬要拿圆筒来打比方的话,应该象个饼干筒,只有顶上一个开口.

管道是"先和者先出",表现得象根水管,所以才取名叫"管道".



二者都可以用相同的方式实现(例如链表,内存块...你能想出N种),区别仅在于指向数据的指针不同,或者通俗地说,数据的索引方式不同.



二者都是非常重要的数据缓冲机制,前者多用于临时数据保存,即"进程内部数据交换",后者则多用于各类输入输出缓冲区,也就是"进程间数据交换".呵呵,把简单问题说复杂是我的强项.

本贴被 rainyss 编辑过,最后修改时间:2008-12-31,15:14:51.

出0入0汤圆

发表于 2008-12-31 12:58:27 | 显示全部楼层
ok

understand

出0入0汤圆

发表于 2008-12-31 12:09:29 | 显示全部楼层
好长~~~~~~~~~~~~~~~

出0入46汤圆

发表于 2008-12-31 11:33:18 | 显示全部楼层
堆和栈的区别

栈(stack)堆(heap)

栈是存放函数返回地址、参数、局部变量的。   

堆是程序可以自由操作的内存,使用时先申请,用完之后释放,如何使用完全由程序代码控制。





栈在汇编代码中表示成PUSH   POP,用的是ESS段,SP寄存器   

而堆不是,是在内存中读写,EDS段,





C++包括两种被应用程序管理的内存区域:一种称为栈(stack),另一种称为堆(heap)。   

stack是函数被调用时自动分配的一块内存区域,它主要用于保留函数内使用的变量及函数调用位置处下一条代码的地址。   

stack是后进先出,一个可变的指针指向stack的顶部。   

本质上,当一个函数被程序调用时,当前的执行地址被放入stack,如果有参数传递到函数内,这些参数也被压入stack,如果函



数内有变量,它们也被压入stack,如果函数执行时调用另一个函数,重复上面的过程。   

当从函数返回时,stack指针指向存放先前执行地址的位置,也就是说,stack空间内分配的元素已被删除。这就是为什么函数



内的变量此时无效,因为它们已经被推出了stack,另外要注意的是,声明一个静态变量,它没有进入stack中。   

另一种由应用程序管理的内存区域是堆(heap),heap是储存应用程序的内存分配需求,并且分离于程序代码和stack,heap中分配



的对象的总的空间受限于计算机系统中有效的虚拟内存。   

C程序通常使用malloc和free分配和回收heap内存,在C++中,使用new和delete.





**********************The Fuck Cutline***************************************************

堆(heap section)

     堆节,咱学过C语言就知道,堆是存放动态分配的变量,比如malloc函数分配的内存,就是在堆上分配的,需要手动释放



,否则就会内存泄露。堆的增长方向,是从内存的低址向高址增长,这个很重要



栈(stack section)

     栈节,保存函数的型参和函数的局部变量。栈的增长方向,是从内存高址向内存低址增长,与堆的增长方向相反

***********************The Fuck Cutline****************************************************



函数里的变量一般是stack,用new和malloc分配的是heap   

stack是有大小限制的,heap的大小与系统虚拟内存差不多   

stack运算比heap快   

stack由编译器来管理,heap由程序员new,   malloc,   delete,   free  



简单地说,堆就是由你自己管理的,而栈是由系统管理的效率方面



1、内存分配方面:



    堆:一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方



式是类似于链表。可能用到的关键字如下:new、malloc、delete、free等等。



    栈:由编译器(Compiler)自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。



2、申请方式方面:



    堆:需要程序员自己申请,并指明大小。在c中malloc函数如p1 = (char *)malloc(10);在C++中用new运算符,但是注意



p1、p2本身是在栈中的。因为他们还是可以认为是局部变量。



    栈:由系统自动分配。 例如,声明在函数中一个局部变量 int b;系统自动在栈中为b开辟空间。



3、系统响应方面:



    堆:操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空



间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空



间中的首地址处记录本次分配的大小,这样代码中的delete语句才能正确的释放本内存空间。另外由于找到的堆结点的大小不



一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。



    栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。



4、大小限制方面:



    堆:是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续



的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵



活,也比较大。



    栈:在Windows下, 栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量



是系统预先规定好的,在WINDOWS下,栈的大小是固定的(是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时



,将提示overflow。因此,能从栈获得的空间较小。



5、效率方面:



    堆:是由new分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便,另外,在WINDOWS下,最好的方



式是用VirtualAlloc分配内存,他不是在堆,也不是在栈是直接在进程的地址空间中保留一快内存,虽然用起来最不方便。但



是速度快,也最灵活。



    栈:由系统自动分配,速度较快。但程序员是无法控制的。



6、存放内容方面:



    堆:一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容有程序员安排。



    栈:在函数调用时第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的地址然后是函数的各



个参数,在大多数的C编译器中,参数是由右往左入栈,然后是函数中的局部变量。 注意: 静态变量是不入栈的。当本次函数



调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点



继续运行。



7、存取效率方面:



    堆:char *s1 = "Hellow Word";是在编译时就确定的;



    栈:char s1[] = "Hellow Word"; 是在运行时赋值的;用数组比用指针速度要快一些,因为指针在底层汇编中需要用edx



寄存器中转一下,而数组在栈上直接读取

 

出0入0汤圆

发表于 2008-12-31 09:45:47 | 显示全部楼层
管道,是个变量呢,以后可以用到,现在不懂

出0入0汤圆

 楼主| 发表于 2008-12-31 09:23:32 | 显示全部楼层
up

出0入0汤圆

发表于 2008-12-30 19:28:36 | 显示全部楼层
楼上的例子略有不当.不应该用管子说事,楼主将来在书上看见"管道"时会晕倒的.

出0入0汤圆

发表于 2008-12-30 19:23:48 | 显示全部楼层
堆像你玩的橡皮泥,需要时挖一块,不玩的时候记得还回来,不然泥巴会越来越少,最后就不够用了。

出1070入962汤圆

发表于 2008-12-30 17:46:22 | 显示全部楼层
栈:后进先出,一个一头封闭的管子,从开口放进去东西,最后放进去的最先被取出来。

出0入0汤圆

发表于 2008-12-30 17:28:47 | 显示全部楼层
堆:就像一堆糖,随便申请随便拿

栈:就像一块千层糕,必须一层一层顺序着用~~~~

出0入0汤圆

发表于 2008-12-30 17:20:23 | 显示全部楼层
堆 => 沙堆,石堆,柴堆

栈 => 只能按一定顺序放入和取出的一种堆,后出先出.

出0入0汤圆

发表于 2010-7-14 19:28:18 | 显示全部楼层
堆和栈的区别(转过无数次的文章) 收藏
一、预备知识—程序的内存分配  
  一个由C/C++编译的程序占用的内存分为以下几个部分  
  1、栈区(stack)—   由编译器自动分配释放   ,存放函数的参数值,局部变量的值等。其  
  操作方式类似于数据结构中的栈。  
  2、堆区(heap)   —   一般由程序员分配释放,   若程序员不释放,程序结束时可能由OS回  
  收   。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。  
  3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的  
  全局变量和静态变量在一块区域,   未初始化的全局变量和未初始化的静态变量在相邻的另  
  一块区域。   -   程序结束后由系统释放。  
  4、文字常量区   —常量字符串就是放在这里的。   程序结束后由系统释放  
  5、程序代码区—存放函数体的二进制代码。  
   
   
  二、例子程序   
  这是一个前辈写的,非常详细   
  //main.cpp   
  int   a   =   0;   全局初始化区   
  char   *p1;   全局未初始化区   
  main()   
  {   
  int   b;   栈   
  char   s[]   =   "abc";   栈   
  char   *p2;   栈   
  char   *p3   =   "123456";   123456\0在常量区,p3在栈上。   
  static   int   c   =0;   全局(静态)初始化区   
  p1   =   (char   *)malloc(10);   
  p2   =   (char   *)malloc(20);   
  分配得来得10和20字节的区域就在堆区。   
  strcpy(p1,   "123456");   123456\0放在常量区,编译器可能会将它与p3所指向的"123456"  
  优化成一个地方。   
  }   
   
   
  二、堆和栈的理论知识   
  2.1申请方式   
  stack:   
  由系统自动分配。   例如,声明在函数中一个局部变量   int   b;   系统自动在栈中为b开辟空  
  间   
  heap:   
  需要程序员自己申请,并指明大小,在c中malloc函数   
  如p1   =   (char   *)malloc(10);   
  在C++中用new运算符   
  如p2   =   new   char[10];   
  但是注意p1、p2本身是在栈中的。   
   
   
  2.2   
  申请后系统的响应   
  栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢  
  出。   
  堆:首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,  
  会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表  
  中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的  
  首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放本内存空间。  
  另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部  
  分重新放入空闲链表中。   
   
  2.3申请大小的限制   
  栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意  
  思是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的大小是2M(也有  
  的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将  
  提示overflow。因此,能从栈获得的空间较小。   
  堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储  
  的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小  
  受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。   
   
   
   
  2.4申请效率的比较:   
  栈由系统自动分配,速度较快。但程序员是无法控制的。   
  堆是由new分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便.   
  另外,在WINDOWS下,最好的方式是用VirtualAlloc分配内存,他不是在堆,也不是在栈是  
  直接在进程的地址空间中保留一块内存,虽然用起来最不方便。但是速度快,也最灵活。  
     
   
  2.5堆和栈中的存储内容   
  栈:   在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可  
  执行语句)的地址,然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈  
  的,然后是函数中的局部变量。注意静态变量是不入栈的。   
  当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地  
  址,也就是主函数中的下一条指令,程序由该点继续运行。   
  堆:一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容由程序员安排。   
   
  2.6存取效率的比较   
   
  char   s1[]   =   "aaaaaaaaaaaaaaa";   
  char   *s2   =   "bbbbbbbbbbbbbbbbb";   
  aaaaaaaaaaa是在运行时刻赋值的;   
  而bbbbbbbbbbb是在编译时就确定的;   
  但是,在以后的存取中,在栈上的数组比指针所指向的字符串(例如堆)快。   
  比如:   
  #include   
  void   main()   
  {   
  char   a   =   1;   
  char   c[]   =   "1234567890";   
  char   *p   ="1234567890";   
  a   =   c[1];   
  a   =   p[1];   
  return;   
  }   
  对应的汇编代码   
  10:   a   =   c[1];   
  00401067   8A   4D   F1   mov   cl,byte   ptr   [ebp-0Fh]   
  0040106A   88   4D   FC   mov   byte   ptr   [ebp-4],cl   
  11:   a   =   p[1];   
  0040106D   8B   55   EC   mov   edx,dword   ptr   [ebp-14h]   
  00401070   8A   42   01   mov   al,byte   ptr   [edx+1]   
  00401073   88   45   FC   mov   byte   ptr   [ebp-4],al   
  第一种在读取时直接就把字符串中的元素读到寄存器cl中,而第二种则要先把指针值读到  
  edx中,再根据edx读取字符,显然慢了。   
   
   
  2.7小结:   
  堆和栈的区别可以用如下的比喻来看出:   
  使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就  
  走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自  
  由度小。   
  使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由  
  度大。   (经典!)  



本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/hairetz/archive/2009/04/30/4141043.aspx

出0入0汤圆

发表于 2010-7-14 19:32:24 | 显示全部楼层
我也问过这个问题,搜索我的帖,有不少精彩回复,当然也会看我很菜

出0入0汤圆

发表于 2010-7-15 09:29:25 | 显示全部楼层
thank you very much.

出0入0汤圆

发表于 2010-7-15 13:28:48 | 显示全部楼层
thanks a lot!

出0入0汤圆

发表于 2010-7-15 14:48:35 | 显示全部楼层
MARK

出0入0汤圆

发表于 2010-7-15 15:44:25 | 显示全部楼层
标记 学习

出0入0汤圆

发表于 2010-7-15 17:18:44 | 显示全部楼层
good.Have a look.

出0入0汤圆

发表于 2010-7-16 08:59:16 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-7-17 08:08:13 | 显示全部楼层
我也不明白,等高手解答!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-27 23:20

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表