程序中的内存分配

栈由操作系统自动分配释放 ,用于存放函数的参数值、局部变量等,其操作方式类似于数据结构中的栈

1. 函数中定义的局部变量按照先后定义的顺序依次压入栈中,也就是说相邻变量的地址之间不会存在其它变量。

2. 栈的内存地址生长方向与堆相反,由高到底,所以后定义的变量地址低于先定义的变量

3. 栈中存储的数据的生命周期随着函数的执行完成而结束

堆由程序员分配释放, 若程序员不释放,程序结束时由OS回收,分配方式倒是类似于链表

1. 堆的内存地址生长方向与栈相反,由低到高,但需要注意的是,后申请的内存空间并不一定在先申请的内存空间的后面

原因是先申请的内存空间一旦被释放,后申请的内存空间则会利用先前被释放的内存,从而导致先后分配的内存空间在地址上不存在先后关系

 

关于堆上内存空间的分配过程:

1. 操作系统有一个记录空闲内存地址的链表

2. 当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆节点

3. 将该节点从空闲节点链表中删除,并将该节点的空间分配给程序

对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确地释放本内存空间。

由于找到的堆节点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表

 

堆与栈区别:
堆与栈实际上是操作系统对进程占用的内存空间的两种管理方式,主要有如下几种区别:
(1)管理方式不同。栈由操作系统自动分配释放,无需我们手动控制;堆的申请和释放工作由程序员控制,容易产生内存泄漏;

(2)空间大小不同。每个进程拥有的栈的大小要远远小于堆的大小。理论上,程序员可申请的堆大小为虚拟内存的大小,进程栈的大小64bits的Windows默认1MB,64bits的Linux默认10MB;

(3)生长方向不同。堆的生长方向向上,内存地址由低到高;栈的生长方向向下,内存地址由高到低。

(4)分配方式不同。堆都是动态分配的,没有静态分配的堆。

        栈有2种分配方式:

              静态分配和动态分配。静态分配是由操作系统完成的,比如局部变量的分配。

              动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由操作系统进行释放,无需我们手工实现

(5)分配效率不同。

         栈由操作系统自动分配,会在硬件层级对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。

         堆则是由C/C++提供的库函数或运算符来完成申请与管理,实现机制较为复杂,频繁的内存申请容易产生内存碎片。显然,堆的效率比栈要低得多。

(6)存放内容不同。栈存放的内容,函数返回地址、相关参数、局部变量和寄存器内容等。当主函数调用另外一个函数的时候,要对当前函数执行断点进行保存,需要使用栈来实现,

        首先入栈的是主函数下一条语句的地址,即扩展指针寄存器的内容(EIP),然后是当前栈帧的底部地址,

        即扩展基址指针寄存器内容(EBP),再然后是被调函数的实参等,一般情况下是按照从右向左的顺序入栈,

        之后是被调函数的局部变量,注意静态变量是存放在数据段或者BSS段,是不入栈的。出栈的顺序正好相反,

        最终栈顶指向主函数下一条语句的地址,主程序又从该地址开始执行。堆,一般情况堆顶使用一个字节的空间来存放堆的大小,而堆中具体存放内容是由程序员来填充的。

从以上可以看到,堆和栈相比,

堆: 由于大量malloc()/free()或new/delete的使用,容易造成大量的内存碎片,并且可能引发用户态和核心态的切换,效率较低

栈: 在程序中应用较为广泛,最常见的是函数的调用过程由栈来实现,函数返回地址、EBP、实参和局部变量都采用栈的方式存放。

      虽然栈有众多的好处,但是由于和堆相比不是那么灵活,有时候分配大量的内存空间,主要还是用堆

 

无论是堆还是栈,在内存使用时都要防止非法越界,越界导致的非法内存访问可能会摧毁程序的堆、栈数据,轻则导致程序运行处于不确定状态,获取不到预期结果,重则导致程序异常崩溃,这些都是我们编程时与内存打交道时应该注意的问题

参考资料:

https://blog.csdn.net/K346K346/article/details/80849966

转载于:https://www.cnblogs.com/allenhaozi/p/11109788.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/550369.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python传中文参数_解决Python传递中文参数的问题

今天有个需要需要传递中文参数给URL但是在GBK环境下的脚本传递GBK的参数老是给我报UNICODE的解码错误。烦的很。所以我们果断选择用urlencode来处理中文,由于国内外网站编码不同,国内是GBK的,国外是UTF8的。>>> import sys>>&…

数据结构php语言,PHP语言做网页开发,会用到什么数据结构,算法?

回复讨论(解决方案)这个要根据项目而定的,PHP做开发,首先得会html javascript不是 会用到什么数据结构,算法而是你将 什么数据结构,算法 用到网页开发中去这个要根据项目而定的,PHP做开发,首先得会html jav…

pythonpptx 楷体_python-pptx 实践 4:添加形状、文本

1、添加流程箭头#加载库importosfrom pptx importPresentationfrom pptx.util importInches, Ptfrom pptx.enum.text importPP_ALIGNfrom pptx.enum.shapes importMSO_SHAPEfrom pptx.dml.color importRGBColor#设置路径work_path rE:\pyspace\tmp\pptxos.chdir(work_path)#实…

C# DevExpress XtraMessageBox自定义字体,字体大小,自定义按钮大小,自定义Icon

1.使用XtraMessageBoxForm,自定义Icon 2.重写XtraMessageBoxForm,自定义消息字体,标题字体 3.注册XtraMessageBoxForm的Showing事件,自定义按钮字体及按钮大小 具体代码如下,只写了简单两种方法,可自己扩展…

php维护页面,php – Symfony2中的“维护网站”页面

我跟着这个tutorial.这非常简单直接.这是我所需要的.您只需更改参数然后清除prod缓存,您仍然可以在dev或测试环境中访问该应用程序.在你的parameters.yml中添加:parameters:maintenance: false #turn it to true to enable maintenanceunderMaintenanceUntil: tomor…

批处理结束某个进程_进程调度

当计算机系统是多道程序设计系统时,常常会出现多个进程或线程竞争CPU的情况。如果有大于处理器数的进程(线程)处于就绪态时,就必须要选择下一个要执行的进程(线程)。在操作系统,用于选择接下来要执行的进程的程序称之为调度程序(Scheduler)&a…

[RN] 可播放视频的播放器版本

可播放视频的播放器版本 "react": "16.6.3", "react-native": "0.57.8", "react-native-orientation": "^3.1.0", "react-native-vector-icons": "^4.3.0", "react-native-video":…

有限元python编程流行吗_Python进行有限元分析

本博客主要是来讲述采用Python语言,利用直接刚度法,来编写求解《有限元方法基础教程》(第五版) 的例题2.1。(也许有的人认为商业软件已经和普及了,没有 必要再自己进行编程了,但是龙猪在这里建议大家还是去了解一下有限元的原理&a…

java用中根后根序列构造二叉树,106. 从中序与后序遍历序列构造二叉树

题目描述根据一棵树的中序遍历与后序遍历构造二叉树。注意:你可以假设树中没有重复的元素。示例:例如,给出中序遍历 inorder [9,3,15,20,7]后序遍历 postorder [9,15,7,20,3]返回如下的二叉树:3/ \9 20/ \15 7思路1.思路与105. 从前序与中序…

Python_selenium之获取当前页面的href属性,id属性,图片信息和截全屏

一、 获取当前页面的全部信息 1. 图片信息包括图片名称、图片大小等信息 2. 只需将图片信息打印出来(image.text image.size image.tag_name) 二、 获取页面元素的href属性(id同理) 1. 获取当前页面所有的链接信息&#xff0…

动态游标for循环_数据结构系列循环链表

前面留的一个问题,后文更跟新回答单链表可以表示任意的线性关系,有些线性关系是循环的,既没有队尾元素。将单链表中的终端结点指针端由空指针改为指向头结点,这时的单链表形成国恒一个环,改为循环链表。插入与删除与单链表的原理甚…

php对数组进行合成的函数,php合并数组函数array_merge()

array_merge()函数在php中是对数组进行合并的,可以把多个数组合成一个数组,并且不改变原数组的值了,但今天我在使用array_merge合并数组时碰到几个小细节上的问题,下面我举例子给各位朋友看看1.array_merge()合并$array array(a&…

Day01,python爬虫基础

今日内容: 爬虫课程: 一爬虫基本原理 二requests请求库 一爬虫基本原理 1、什么是爬虫? 爬虫就是爬取数据。 2、什么是互联网? 由一堆网络设备,把一台台的计算机互联到一起称之为互联网。 3、互联网建立的目的 数据的传递与数据的共享。 4、什么是数据? 例如: 电…

sas sql 读取最后一行数据_SAS基础编程和数据处理

前几天讲了数据分析中SQL的基本使用方法以及具体案例分析思路,接下来会继续讲统计基础以及在SAS软件内的应用,在这之前,本文先进行SAS基础使用编程的基础介绍,后续会主要阐述SAS软件内的统计数学的应用,如分析或初步建…

python 列表索引位置,python – 在列表中查找值的第一个位置

一种方法是为项目创建单独的列表以查找索引并使用索引函数和使用列表理解(还要进行额外检查以确保项目在列表中,否则将发生ValueError):my_list [1,1,1]items [1,2]print ([my_list.index(item) if item in my_list else -1 for item in items])输出:[…

Linux 下配置多路径及SCSI扫描磁盘重新发现大小

Linux SCSI扫描磁盘重新发现大小: # for i in find /sys/class/scsi_host/host*; do echo 1 >> $i/issue_lip; echo "- - -" >> $i/scan; done 1、安装多路径软件包:device-mapper-1.02.67-2.el5device-mapper-event-1.02.67.2.el…

代码合并工具_分享几款比较常用的代码比较工具

俗话说:三句不离本行,对于程序员这个可爱的群体来说也是一样,即使面对无休无止的编程工作,程序员们依旧任劳任怨的埋头苦干,梦想着用自己码下的代码改变世界。工欲善其事,必先利其器,每一位程序员都有自己私…

oracle9i 恢复数据库,Oracle9i RMAN备份及恢复步骤(zt)

1、切换服务器归档模式,如果已经是归档模式可跳过此步:%sqlplus /nolog (启动sqlplus)SQL> conn / as sysdba (以DBA身份连接数据库)SQL> shutdown immediate; (立即关闭数据库)SQL> startup mount (启动实例并加载数据库,但不打开)…

python 计量经济 35岁 工作_Python在计量经济与统计学中的应用

Python for Econometrics and Statistics (Python在计量经济与统计学中的应用) 【点击链接进入主页】。这套笔记将重点介绍Python在计量经济学与统计分析中的应用。内容涵盖Python基本数据类型,Numpy科学运算,Pandas数据分析,统计分析&#x…

循环控制

循环控制 定义 Python 循环语句是通过一条或多条语句的执行结果(True 或者 False)来决定执行的代码块。 并在符合条件的情况下跳出该段循环。 类似于控制语句。 如下图所示。 WHILE 循环 while 判断条件: 语句 求1~100的和 n 0 sum 0 while…