随笔 - 67, 文章 - 0, 评论 - 375, 引用 - 15
数据加载中……

OutOfMemory这家伙是谁?为什么我还留有许多内存,它却使进程崩溃了?


原文地址:Who is this OutOfMemory guy and why does he make my process crash when I have plenty of memory left?
发布时间:Friday, November 25, 2005 10:43 AM
作  者:Tess  

为了回答这个问题,我们先来看看一些概念。

工作在32位系统上,可以寻址4GB内存。典型地, 其中2GB留给操作系统,另外2GB则用于各个用户态的进程,如w3wp.exe(asp.net)进程。这块2GB的内存叫做虚拟内存,它和另外附加的RAM是独立的。RAM的大小仅决定了有多少内存分页和交换可用,如,程序多快能访问它们。

一个进程分配内存时,它是这样进行的:首先,预定虚拟内存;然后,提交内存到该块中(这是实际使用的内存)。提交的内存叫做私有字节。

虚拟地址空间用于存放进程中的一些项目,例如:

  • 动态链接库
  • 本地堆(非.net堆)
  • 线程(每个线程保留1MB内存堆栈)
  • .net堆(托管变量)
  • .net装载堆(程序集及相关的结构变量)
  • com组件分配的虚拟内存

虚拟分配的内存并不是次序排列的(或者很少按次序排列)。例如,dll会装载在各自的地址空间,因此dll间会留下内存空隙。另外,重新分配的虚拟内存间也会留下空隙。这就意味着尽管拥有2GB的虚拟内存,你却不可能完全使用它。因为使用了足够多的内存后,这块内存看起来就会像瑞士硬干酪,起码得有足够的空间让你的叉子能叉进去吧?

这就是遇上OutOfMemory异常时发生的东西。

以后我可能会讨论更多关于.net内存管理知识,但现在我将只做简单介绍,因为已经有一些很好的博客对此加以介绍了,如Maoni的CLR性能博客 http://blogs.msdn.com/maoni/ 和http://blogs.msdn.com/yunjin

在.net框架中,垃圾回收器就是内存管理者,它以堆的方式预定虚拟内存。一旦这些堆被分配,就会创建新的.net对象实例。这个对象将被存储在堆内存断中,此时也将内存提交。

在.net框架1.1(服务器版本)中,会创建规则的.net堆, 大小为64MB。(若使用8+处理器或手动改变设置,该堆大小会有所变动。在这里先忽略这些情况,而仅讨论一般的情形)


这些64MB的片断需以一大整块的形式分配,而不能在这里分配32MB,在那里分配32MB。因此这些64MB的内存片断填充完后,就需要在2GB的内存空间中去寻找一块64MB或更大的空闲内存块,用以分配新的内存块。若这样大小的空闲内存块没了,就会发生OutOfMemory异常。

这些OutOfMemory 异常通常不是致命的,但仍然很糟糕,因为它们会使进程处于一种不稳定的状态。然而,当垃圾回收器做内存整理时,它本身的内也需要空间,这样它才能整理内存。且使用的内存越多,也将需要越多的这些内部结构体。若没有留给垃圾回收器足够的空间用于垃圾整理,就会产生一个致命的内存异常,进程也将终结。

由上所知,预定的内存(性能监视器中的虚拟字节)将比提交的内存字节(性能监视器中的私有字节)大得多。通常在内存使用率高的时候,差别大约是500MB.当虚拟字节达到大约1.2-1.4GB的时候,再寻找64MB的空闲块将变得非常困难,这意味着此时一个正常的.net进程将会发生OutOfMemory异常。

再次声明,这个值可能会因应用程序或装载的dll和本地com组件的内存分配模式(等等)不同会有所差别。

现在该知道为什么会出现OutOfMemory 异常了吧?尽管仍然还有许多的RAM可用。下一任务是去找出为什么使用这些内存,我将会花些时间在我以后的博客帖子中加以讨论。

posted on 2006-10-20 22:40 Ring 阅读(2137) 评论(5)  编辑 收藏 网摘 所属分类: C 翻译文章

评论

#1楼    回复  引用    

我也遇到同样的问题,当w3wp.exe用了大于1G的内存时OutOfMemory就会出现.
请问如何才能避免这样的错误出现?
2006-10-21 08:54 | wwonion [未注册用户]

#2楼    回复  引用  查看    

问题是一但系统装上4G内存,ASP.NET随时都会抛出OutOfMemory;如果只装2G或更少的内存,却不会发生这种现象。所以出这个异常,还有一个原因是在操作系统本身。
2006-10-21 09:11 | Edwin Liu      

#3楼    回复  引用  查看    

大于1G的内存也会出问题吗?解决办法就是修改配置machine.config文件,将进程的内存使用率设小一点(默认为系统总内存的60%)。
2006-10-21 09:17 | Edwin Liu      

#4楼    回复  引用  查看    

可以使用3GB模式
或者通过代码减少内存占用
2006-10-21 09:24 | Ricktroy[匿名]      

#5楼    回复  引用  查看    

工作在32位系统上,可以寻址4GB内存

厉害
2006-10-21 14:46 | aspnetx      




标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2006-11-16 11:36 编辑过
Google站内搜索

China-pub 计算机图书网上专卖店!6.5万品种 2-8折!
近千种 9-95 新二手计算图书火热销售中!
开发者征途系统新作:《设计模式——基于C#的工程化实现及扩展》

相关文章:

相关链接: