在什么情况下不能释放可重定位内存的分区分配目的分区,如何判断

内存分区应该注意的地方
在C++中,内存分成5个区,他们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。
栈,就是那些由编译器在需要的时候分配,在不需要的时候自动清楚的变量的存储区。里面的变量通常是局部变量、函数参数等。
堆,就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。
自由存储区,就是那些由malloc等分配的内存块,他和堆是十分相似的,不过它是用free来结束自己的生命的。
全局/静态存储区,全局变量和静态变量被分配到同一块内存中,在以前的C语言中,全局变量又分为初始化的和未初始化的,在C++里面没有这个区分了,他们共同占用同一块内存区。
常量存储区,这是一块比较特殊的存储区,他们里面存放的是常量,不允许修改(当然,你要通过非正当手段也可以修改,而且方法很多)明确区分堆与栈
在bbs上,堆与栈的区分问题,似乎是一个永恒的话题,由此可见,初学者对此往往是混淆不清的,所以我决定拿他第一个开刀。
首先,我们举一个例子:
void f() { int* p=new int[5]; }
这条短短的一句话就包含了堆与栈,看到new,我们首先就应该想到,我们分配了一块堆内存,那么指针p呢?他分配的是一块栈内存,所以这句话的意思就是:在栈内存中存放了一个指向一块堆内存的指针p。在程序会先确定在堆中分配内存的大小,然后调用operator new分配内存,然后返回这块内存的首地址,放入栈中,他在VC6下的汇编代码如下:
operator new ()
dword ptr [ebp-8],eax
eax,dword ptr [ebp-8]
dword ptr [ebp-4],eax
这里,我们为了简单并没有释放内存,那么该怎么去释放呢?是delete p么?澳,错了,应该是delete []p,这是为了告诉编译器:我删除的是一个数组,VC6就会根据相应的Cookie信息去进行释放内存的工作。
好了,我们回到我们的主题:堆和栈究竟有什么区别?
主要的区别由以下几点:
1、管理方式不同;
2、空间大小不同;
3、能否产生碎片不同;
4、生长方向不同;
5、分配方式不同;
6、分配效率不同;
管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制,容易产生memory leak。
空间大小:一般来讲在32位系统下,堆内存可以达到4G的空间,从这个角度来看堆内存几乎是没有什么限制的。但是对于栈来讲,一般都是有一定的空间大小的,例如,在VC6下面,默认的栈空间大小是1M(好像是,记不清楚了)。当然,我们可以修改:
打开工程,依次操作菜单如下:Project-&Setting-&Link,在Category 中选中Output,然后在Reserve中设定堆栈的最大值和commit。注意:reserve最小值为4Byte;commit是保留在虚拟内存的页文件里面,它设置的较大会使栈开辟较大的值,可能增加内存的开销和启动时间。
碎片问题:对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出,在他弹出之前,在他上面的后进的栈内容已经被弹出,详细的可以参考数据结构,这里我们就不再一一讨论了。
生长方向:对于堆来讲,生长方向是向上的,也就是向着内存地址增加的方向;对于栈来讲,它的生长方向是向下的,是向着内存地址减小的方向增长。
分配方式:堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。
分配效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作系统)在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会分到足够大小的内存,然后进行返回。显然,堆的效率比栈要低得多。
从这里我们可以看到,堆和栈相比,由于大量new/delete的使用,容易造成大量的内存碎片;由于没有专门的系统支持,效率很低;由于可能引发用户态和核心态的切换,内存的申请,代价变得更加昂贵。所以栈在程序中是应用最广泛的,就算是函数的调用也利用栈去完成,函数调用过程中的参数,返回地址, EBP和局部变量都采用栈的方式存放。所以,我们推荐大家尽量用栈,而不是用堆。
虽然栈有如此众多的好处,但是由于和堆相比不是那么灵活,有时候分配大量的内存空间,还是用堆好一些。
无论是堆还是栈,都要防止越界现象的发生(除非你是故意使其越界),因为越界的结果要么是程序崩溃,要么是摧毁程序的堆、栈结构,产生以想不到的结果,就算是在你的程序运行过程中,没有发生上面的问题,你还是要小心,说不定什么时候就崩掉,那时候debug可是相当困难的:)
对了,还有一件事,如果有人把堆栈合起来说,那它的意思是栈,可不是堆,呵呵,清楚了?
“堆”的英语是heap;“堆栈”=“栈”,英语是stack。我们避开计算机方面的意义,只看日常用义。查《The Little Oxford Dictionary》(相当于《新华字典》的样子),有:heap: [noun] (esp. in plural) [colluquial] la ...stack: [noun] (esp. orderly) ...可以看出,两个都是堆、叠的意思,区别就在于,heap是杂乱无序的,而stack是有序的。举个例子说,如果是一叠纸牌,没洗过乱放的就是heap,洗过的放整齐了就是stack。因为两个词本来意思比较接近,所以也有通用之处。
在计算机上,堆和栈一般指两种数据结构。“堆”是金字塔形的结构,只要求上面的都比下面的值大(或相反),不那么有序;“栈”是线性的结构,有严格的先后进出次序。这就是其区别的直观解释。
再说汉语的问题。汉语译者把heap译成“堆”,是直译;而把stack称为“栈”,则完全是在汉语中另找了一个比喻。所谓“栈”,即“栈道”,是山壁上修出的一段很窄的路,一次仅能容一人通过。用以比喻计算机中“栈”结构的进出的先后次序不能随意。至于“堆栈”呢,我认为完全是一个拼凑出来的东西,反而让人从字面上看不出一点本来的意思了。
添两句堆栈在这个板块基本是称呼内存的2个不同区域但在数据结构中 他们有另外的意义:栈:线性表的一种,它只允许对最后一个元素(被称作栈顶)进行操作 可以在栈顶之后加入一个元素形成新的栈顶(push) 也可以把原来的栈顶移除 "露出"一个新的元素作为栈顶(pop)。堆:一种排序二叉树结构,有大顶堆和小顶堆之分,典型的应用是堆排序(目前没发现它跟我们常说的堆内存区有什么联系)
C++五大内存区楼上已经有人讲了 stack和heap两个区域的划分是因为它们管理方式的不同
栈用于保存函数的局部变量 它跟汇编语言的栈段是同一种东西 它的操作很类似于数据结构里的栈,因此得名。但是 它除了使用栈顶指针和栈指针进行push和pop操作之外 还可以使用栈偏移指针进行随机访问,所以 只有函数调用的时候和函数返回的时候会使用栈顶指针。因为其上的对象销毁只是移动寄存器里保存的指针 所以栈的效率很高。但是 一般栈段的总长度是有限的,过长的递归可能导致栈溢出错误(很常见吧^^)
堆在malloc申请后分配 到free指定时释放 它不会自动释放 是造成内存泄露的主要原因之一 而且 它的空闲和使用情况由操作系统用一个链表来管理 所以一般来说堆的效率不高 尽管语言标准没作任何提示 通常认为堆跟自由存储是同一个区域(好像我看的资料和前面的不一样 Exceptional C++的说法 堆是malloc/free分配的 自由存储是 new/delete分配的)
程序的内存分布+ROM和RAM
内存的五大分区详解
没有更多推荐了,温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
阅读(16937)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
loftPermalink:'',
id:'fks_',
blogTitle:'内存分配的原理__Linux虚拟内存管理(glibc)_Linux的虚拟内存管理有几个关键概念_Linux 虚拟地址空间如何分布_malloc和free是如何分配和释放内存_如何查看堆内内存的碎片情况_既然堆内内存brk和sbrk不能直接释放,为什么不全部使用 mmap 来分配,munmap直接释放呢',
blogAbstract:'\r\nLinux虚拟内存管理(glibc)\r\n&&&&&&& 在使用mysql作为DB开发的兑换券系统中,随着分区表的不断创建,发现mysqld出现了疑似“内存泄露”现象,但通过 valgrind 等工具检测后,并没发现类似的问题(最终原因是由于glibc的内存碎片造成)。\r\n&\r\n因此,需要深入学习 Linux 的虚拟内存管理方面的内容来解释这个现象;Linux 的虚拟内存管理有几个关键概念: 1、每个进程都有独立的虚拟地址空间,进程访问的虚拟地址并不是真正的物理地址; 2、虚拟地址可通过每个进程上的页表(在每个进程的内核虚拟地址空间)与物理地址进行映射,获得真正物理地址; 3、',
blogTag:'',
blogUrl:'blog/static/',
isPublished:1,
istop:false,
modifyTime:8,
publishTime:3,
permalink:'blog/static/',
commentCount:2,
mainCommentCount:2,
recommendCount:1,
bsrk:-100,
publisherId:0,
recomBlogHome:false,
currentRecomBlog:false,
attachmentsFileIds:[],
groupInfo:{},
friendstatus:'none',
followstatus:'unFollow',
pubSucc:'',
visitorProvince:'',
visitorCity:'',
visitorNewUser:false,
postAddInfo:{},
mset:'000',
remindgoodnightblog:false,
isBlackVisitor:false,
isShowYodaoAd:true,
hostIntro:'',
hmcon:'1',
selfRecomBlogCount:'0',
lofter_single:''
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}内存管理的基本技术之分区法
内存管理的基本功能是为待运行的程序分配内存,并在使用结束后回收这些内存。基本的内存管理技术包括分区法、可重定位分区法、覆盖和交换等技术
分区法是一种简单的内存管理方式。在这种方式下,除操作系统占用内存的某个固定分区(通常是低地址部分)外,其余的内存由各应用程序共享使用。分配的方式是将内存划分为若干块(称为分区),用于存储各程序的代码和数据
按分区划分方式,分区法可分为两种:固定分区法和动态分区法
(1)&&&&&&
固定分区法
固定式分区法是指在程序装入内存之前,就将全部内存划分成若干固定大小的分区(每个分区大小固定,但不同分区大小可以不同)。这一划分可由操作人员完成,也可由操作系统完成。一旦分区划分好之后,在系统运行期间,分区的个数和各个分区的大小不再改变。因而,这种分区又称为静态分区
固定分区法在每个分区内只能运行一个进程。通常情况下,为了适应进程大小的差异,将内存划分成大小不同的分区。
为了记录各分区的基本情况和使用状态,系统应建立一个分区说明表,其中包括分区大小、起始地址和是否已分配等信息等。采用这种技术,虽然可使多个作业共驻内存,但一个作业的大小不可能正好等于某个分区的大小,于是在每个分配的分区中很可能有部分内存被浪费
固定式分区实现技术简单,所需操作系统软件和处理开销都小,但其内存利用率不高,仅适用于作业大小和数量都事先比较清楚的系统中
(2)动态分区法
动态分区法是指在装入作业时根据其实际内存容量的需求,动态为作业划分一块连续的内存空间(分区)。也就是说,分区的大小是在作业装入到内存时确定的,大小恰好等于作业的大小
在动态分区法中,系统同样需要设置一种数据结构来记录各分区的基本信息和使用情况,包括各个分区的大小、位置和对各个分区的存取限制等。常用的数据结构有空闲分区表和空闲分区链两种
&空闲分区表
下图给出了一个空闲分区表。内存中每一个未被使用的分区对应该表的一个表项,一个表项中包括分区序号,分区大小,分区的起始地址及该分区的使用状态
&空间分区链
空间分区链式使用链指针把所有的空闲分区链接成一个链表。为了实现对空闲分区的分配和链接,在每个分区的起始部分设置状态位、分区大小和链接各个分区的前后指针,由状态位指示该分区是否已经分配;同时在分区尾部设置一个后向指针,用来链接后面的一个分区;分区的中间部分是用来存入作业的空间内存空间,当该分区分配出去后,状态位就由0置为1
采用动态分区法,当系统初启动时,内存中除了常驻的操作系统外,其余的是一个完整的大空闲区。当作业申请装入内存时,系统就从空闲表(链)中查找一个足以容纳这个作业的空闲区。如果大小恰好一样,则把该去分配给这个作业使用,并相应的修改空闲分区表(链)中的状态位。如果这个空闲区比作业需要的空间大,则将该分区划分为两部分:一部分给作业使用,而零一部分设置为较小的空闲区加入到空闲分区表(链)中。当一个作业完成后,其所释放的分区将其相邻的空闲分区合并起来,组成一个更大的分区
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。五大内存分区_百度文库
您的浏览器Javascript被禁用,需开启后体验完整功能,
享专业文档下载特权
&赠共享文档下载特权
&10W篇文档免费专享
&每天抽奖多种福利
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
五大内存分区
你可能喜欢电脑系统盘怎么怎么清理都不能把内存释放出来,还是满的_百度知道
电脑系统盘怎么怎么清理都不能把内存释放出来,还是满的
答题抽奖
首次认真答题后
即可获得3次抽奖机会,100%中奖。
你说的有些模糊.按我理解应该是说你的C盘满了,想如何清理一下,得到更多磁盘空间.但没有效果.还是满的.对吧. 如果是,那不叫内存,应该叫磁盘存储空间.
关于这个问题就牵扯到系统优化问题上了.如将一些占空间应用程序安装到D盘上,交换分区,临时文件夹,IE的临时文件夹都可以改设到D盘上,关闭如系统还原,减小回收站空间设置或关闭它都是增大C盘空间的有效方法.现在360软件还带有C盘搬家的工具软件,也可帮你做些工作.如有问题可继续加问.
采纳率:66%
内存是在软件运行时的中间缓冲仓库作用,真正的数据是在硬盘上,你平时做的清理工作指的是清理硬盘上的垃圾文件,或说无用文件。至于内存空间只有一个程序被关闭或结束后爱能被释放出来。
嗯,因为你的C盘垃圾文件很少,及时你去C盘删除文件夹也是那样,最好别乱删除最好把你的C盘重新格式化一遍,然后你下载软件什么的。比如说QQ,迅雷什么的最好别往C盘里面放,
不太会的话你在追问
为您推荐:
其他类似问题
您可能关注的内容
内存释放的相关知识
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。}

我要回帖

更多关于 怎么释放系统内存 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信