当前位置: 首页 > 编程日记 > 正文

堆和栈的差别(转过无数次的文章)

一、预备知识—程序的内存分配 
  一个由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分配的内存,一般速度比較慢,并且easy产生内存碎片,只是用起来最方便.   
  另外,在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小结:   
  堆和栈的差别能够用例如以下的比喻来看出:   
  使用栈就象我们去饭馆里吃饭,仅仅管点菜(发出申请)、付钱、和吃(使用),吃饱了就 
  走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的优点是快捷,可是自 
  由度小。   
  使用堆就象是自己动手做喜欢吃的菜肴,比較麻烦,可是比較符合自己的口味,并且自由 
  度大。   (经典!)

相关文章:

ARM WFI和WFE指令【转】

本文转载至:http://www.wowotech.net/armv8a_arch/wfe_wfi.html 1. 前言 蜗蜗很早以前就知道有WFI和WFE这两个指令存在,但一直似懂非懂。最近准备研究CPU idle framework,由于WFI是让CPU进入idle状态的一种方法,就下决心把它们弄清…

分享几个用 Python 给图片添加水印的方法,简单实用

作者 |俊欣来源 |关于数据分析与可视化今天来分享几种可以给图片添加水印的方法,都是十分的简单实用,大家在看了之后也可以私底下去自己试试,有些方法需要的代码量就比较少,有些方法需要的代码量就稍微多一些,那我们开…

Apache服务器下使用 ab 命令进行压力测试

ab是Apache超文本传输协议(HTTP)的性能测试工具。 其设计意图是描绘当前所安装的Apache的执行性能,主要是显示你安装的Apache每秒可以处理多少个请求. #ab -v可以看出其基本信息 #ab -n1000 -c10 http://localhost:81/t.php 这是一个基本命令 -n1000表示总请求数为…

《Objective-c》Foundation框架 -(字符串:NSString和NSMutableString)

一、NSString(不可变字符串) 1.创建字符串的方式:(利用对象方法) 方式一:最快速的创建 方式二: 方式三: 方式四: 方式五:NSUTF8StringEncoding 用到中文就可以…

基于Vue, Vuex 和 ElementUI 构建轻量单页Hexo主题Lite

Hexo Theme Lite Keep Calm, Lite and Writing.light single page blog application theme, using Vue, Vuex, ElementUI and so on. 一款轻量单页博客主题,基于Vue, Vuex 和 ElementUI 构建, 工具语言 Typescript Live Demo Demo | 在线演示 Github 项目地址 Previ…

怎么关闭wordpress评论

1、要是关闭某一篇文章的评论,在发表文章的时候,在下面有个“讨论”,把"允许评论"去掉勾选就可以了。 2、要是关闭所有文章的评论,在“设置”-“讨论设置”把“默认文章设置”中的“允许访客对新文章发表评论 ”不再勾…

ACM-ICPC历届世界总冠军名单1977-2015

为什么80%的码农都做不了架构师?>>> ‍‍‍‍‍‍ ACM-ICPC历届世界总冠军1977-2015 更新时间2016-04-20 17:39 年份总决赛地点冠军大学国家2015年摩洛哥马拉喀什‍‍‍‍聖彼得堡國立資訊科技、機械與光學大學 (破纪录解出全部题目)‍‍‍‍俄罗斯2014…

AI 盯上了外包司机,看后视镜就被扣分,奖金拜拜!

整理 | 梦依丹 来源 | CSDN 生活在科技领先时代的我们,每天无不被算法支配着,从衣食住行到工作中的决策参考。以前在电影中见到的AIer控制人类的场景,越来越现实化。 AI算法不断优化之下,有些企业直接通过AI来给员工打绩效&…

用 Handler 轻松实现专属Android定时器

今年在项目中发现为了实现倒计时、时间段的延迟执行、时间段的轮询执行任务,都是采用Handler postDelayed(runnable,delayMillis). 等等,这有毛病?那你将实现以上功能时、代码大概如下。 Handler handler new Handler(); int cou…

查看Firefox中的缓存

在firefox浏览器中可以在地址栏使用about:cache命令查看当前缓存。 Information about the Cache Service Disk cache device Number of entries:333Maximum storage size:458708 KiBStorage in use:3685 KiBCache Directory:C:\Documents and Settings\Administrator\Local …

技术大咖齐聚爱数智慧人机交互技术论坛 | CNCC2021

CNCC2021【人机交互技术的机遇与挑战】技术论坛将于2021年10月28日13:00-16:00在深圳国际会展中心CC105B召开,本次论坛由CCF主办,爱数智慧创始人兼CEO张晴晴担任论坛主席,邀请来自产学研各界技术大咖,就人机交互、智能语音技术的应…

响应式网页的布局设计

值得收藏的14款响应式前端开发框架 作为今年大热的设计趋势,响应式已然是设计师的标配技能。今天阿里的同学从响应式设计的布局类型、布局实现两方面深入讲解,有哪些实现布局的方式,该采用何种方式,都有相当专业细致的解答&#x…

halcon算子翻译——set_framegrabber_callback

名称 set_framegrabber_callback - 为图像采集设备注册一个回调函数。 用法 set_framegrabber_callback( : : AcqHandle, CallbackType, CallbackFunction, UserContext : ) 描述 算子set_framegrabber_callback为AcqHandle指定的图像采集设备注册一个回调函数。 参数CallbackF…

设置Sysctl.conf用以提高Linux的性能(最完整的sysctl.conf优化方案)

Sysctl是一个允许您改变正在运行中的Linux系统的接口。它包含一些 TCP/IP 堆栈和虚拟内存系统的高级选项, 这可以让有经验的管理员提高引人注目的系统性能。用sysctl可以读取设置超过五百个系统变量。基于这点,sysctl(8) 提供两个功能:读取和…

AI 天气预报准确度高于气象台,一张 GPU 1秒预测未来 90 分钟天气

编译 | 禾木木 出品 | AI科技大本营(ID:rgznai100) 此次 DeepMind 聚焦天气预报这一重大挑战,与英国气象局合作将 AI 应用于预测降雨。 在天气现象中,雨尤其重要,因为它会影响我们的日常决策。 我应该带伞吗&#xff1…

33.搜索插件——autocomplete

搜索插件的功能是通过插件的autocomplete()方法与文本框相绑定,当文本框输入字符时,绑定后的插件将返回与字符相近的字符串提示选择,调用格式如下: $(textbox).autocomplete(urlData,[options]); 其中,textbox参数为文…

React Native开源项目如何运行(附一波开源项目)

学习任何技术,最快捷的方法就是学习完基础语法,然后模仿开源项目进行学习,React Native也不例外。React Native推出了1年多了, 开源项目太多了,我们以其中一个举例子.给大家演示下如何运行开源项目.(前提是你已经搭建好…

http header头设置反向代理不缓存

一:概念说明 Expries:网页的cache过期时间,到指定日期网页cache失效 Last-Modified:网页的最新更新时间 Cache-Control 缓存控制 no-cache:不缓存网页 no-store:不缓存网页,如果有则删除之 must-revalidate:使之前,服务器响应使用…

985大学的高材生只会写代码片段,丢人吗?

很多同学在学习编程的时候都会遇到各种各样的难题,比如:没有合适的资料、学习过于碎片化、资料的质量层次不齐、看了很多视频自己动手时却还是不会、接触不到完整项目、无法检测自己的编程水平是不是企业所认可的……最近,小郭和小解同学也遇…

xcode6 dyld_sim is not owned by root

如果运行复制过来的xcode可能会这个提示,xcode6 dyld_sim is not owned by root解决方法打开终端 输入sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer

C语言关闭日志文件时忘了将日志文件全局变量指针置为NULL

C语言写了一个write_log函数以写日志,写了一个close_log_file函数以关闭日志,声明了一个日志文件全局变量文件指针plogFile。 write_log中首先判断plogFile是否为NULL,如果不为NULL,则直接引用plogFile写日志信息; 如果…

DeepMind 的新强化学习系统是迈向通用 AI 的一步吗?

作者 | Ben Dickson来源 | 数据实战派这篇文章是我们对 AI 研究论文评论的一部分,这是一系列探索人工智能最新发现的文章。对于已经精通围棋、星际争霸 2 和其他游戏的深度强化学习模型来说,人工智能系统的主要挑战之一是它们无法将其能力泛化到训练领域…

linux中iptables入门教程--设置静态防火墙

1、iptables介绍iptables是复杂的,它集成到linux内核中。用户通过iptables,可以对进出你的计算机的数据包进行过滤。通过iptables命令设置你的规则,来把守你的计算机网络──哪些数据允许通过,哪些不能通过,哪些通过的…

{好文备份}SQL索引一步到位

SQL索引一步到位(此文章为“数据库性能优化二:数据库表优化”附属文章之一) SQL索引在数据库优化中占有一个非常大的比例, 一个好的索引的设计,可以让你的效率提高几十甚至几百倍,在这里将带你一步步揭开他…

浅谈SQL Server中统计对于查询的影响

简介SQL Server查询分析器是基于开销的。通常来讲,查询分析器会根据谓词来确定该如何选择高效的查询路线,比如该选择哪个索引。而每次查询分析器寻找路径时,并不会每一次都去统计索引中包含的行数,值的范围等,而是根据一定条件创建…

《Effective C#中文版:改善C#程序的50种方法》读书笔记

一、用属性代替可访问的字段 1、.NET数据绑定只支持数据绑定,使用属性可以获得数据绑定的好处; 2、在属性的get和set访问器重可使用lock添加多线程的支持。 二、readonly(运行时常量)和const(编译时常量) …

100行代码,使用 Pygame 制作一个贪吃蛇小游戏!

作者 | 周萝卜来源 | 萝卜大杂烩相信我们大家都玩过贪吃蛇游戏,今天我们就从头一起来写一个贪吃蛇小游戏,只需要100多行的代码就完成了。用到的 Pygame 函数 贪吃蛇小游戏用到的函数功能描述init()初始化 pygamedisplay.set_mode()以元组或列表为参数创建…

Ubuntu + VirtualBox + windows xp互相访问

2019独角兽企业重金招聘Python工程师标准>>> 1 在ubuntu中安装最新版virtualbox,并且同时安装增强插件 2 设置xp网络位桥接网络 3 启动虚拟机中xp系统 4 关闭虚拟机中xp防火墙 virtualbox原来如此的爽,太方便了 第二天到公司使用网络的时候,基…

cocoapods使用教程

#####一、什么是CocoaPods CocoaPods是一个用来帮助我们管理第三方依赖库的工具。 #####二、安装cocoaPods 1.移除现有Ruby默认源 $gem sources --remove https://rubygems.org/ 复制代码2.使用新的源 $gem sources -a https://ruby.taobao.org/ 复制代码3.验证新源是否替…

Memcached安装以及PHP的调用

一:安装libevent 由于memcached安装时,需要使用libevent类库,所以先安装libevent 1.下载 #wget http://www.monkey.org/~provos/libevent-2.0.12-stable.tar.gz 2.解压缩 #tar xzfv libevent-2.0.12-stable.tar.gz 3.进入目录 #cd l…