架构师_程序员

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 146|回复: 0

[资料] .Net内存溢出(System.OutOfMemoryException)的常见情况

[复制链接]
发表于 2019-3-14 21:47:39
在什么情况下会出现OutOfMemonryException呢? 在我们试图新建一个对象时,而垃圾收集器又找不到任何可用内存时被抛出,这种情况下我们是可以捕获该异常的; 另一种情况是,CLR需要内存时,而却系统却不能提供,也会抛出该异常. 但此时,我们的应用程序是不能捕获该错误的.

内存溢出(OutOfMemoryException)的调试分析

32位操作系统的寻址空间是4G,其中有2G被操作系统占用,也就是说留给用户进程的内存只有2G(其中还要扣除程序加载时映像占用的部分空间,一般只有1.6G~1.8G左右可以使用)。 如果进程运行中需要申请内存,而操作系统无法为其分配内存空间,则会产生内存不足的异常,在.net中为System.OutOfMemoryException(The exception that is thrown when there is not enough memory tocontinue the execution of a program.)。 虽然最终的表现都为OutOfMemoryException,但其产生的原因可能是不一样的,动手解决此问题之前需要先对进程当前内存的使用状态进行分析,找出正确的原因,才能对症下药。下面分享一下调试此类问题的一些心得。

更多内容请参考:http://blog.csdn.net/lazyleland/article/details/6704661

iis应用程序池 内存溢出错误 System.OutOfMemoryException

在ASP.NET Web服务器上,ASP.NET所能够用到的内存,通常不会等同于所有的内存数量。在machine.config配置文件中,配置节<processModel>中有一个属性“memoryLimit”,这个属性的值是一个百分值,默认为“60”,即指定了ASP.NET进程(在任务管理器中大家就可以看到ASP.NET的进程,IIS5中为aspnet_wp,IIS6中为w3wp)能够使用所有物理内存的60%。当ASP.NET使用的内存量超过这个限额时,IIS会开始自动回收(recycle)进程,即创建一个新的进程去负责应付Http请求,而将旧进程所占用的内存回收。

当我们有一台很大内存的服务器时,“memoryLimit”这个值是需要进行适当的调整的。比如我们准备了一台chemas-microsoft-com ffice marttags" />t="on">4G内存的服务器,那么t="on">4G×60%=t="on">2.4G。但是,对于Win32操作系统,一个进程所能占用的所有内存空间只有t="on">2G。当ASP.NET进程占用的内存开始达到t="on">2G时,由于它并没有达到t="on">2.4G的“回收阈值”,所以IIS不会启动recycle进程操作,但是由于Win32的限制,实际上已经不能给这个进程分配更多的内存了,于是,OutOfMemoryException就很可能会被抛出了。为了避免这样的情况,我们就必须将“memoryLimit”适当调小,以让IIS更早的进行进程回收。

微软推荐的ASP.NET进程占用内存是不超过60%,并最好使计算出的实际值不超过t="on">800M。就是说,对于一台t="on">4G内存的服务器,最好将“memoryLimit”属性设置成“20”。设置一个适当的回收阈值,让IIS适时的进行进程回收,对于保证整个服务器的稳定运行,避免OutOfMemoryException是非常重要的。

在IIS6中,ASP.NET进程的回收阈值不再由配置节中的“memoryLimit”属性决定,而是由IIS管理器中的应用程序池配置中的设置决定。

但是,即使正确设置了这些配置,也不能保证完全避免OutOfMemoryException的发生,原因可能是多样而复杂的,比如内存回收操作可能耗时太多等等。开发人员要注意的,就是在代码中时刻牢记不要无谓的使用和浪费内存。:)

如果你有一台大内存的服务器,同时对Win32操作系统中对于进程最高使用t="on">2G内存的限制很郁闷,可选的解决方法有两个:

  • 使用/3GB模式启动计算机,方法参加文后的链接
  • 使用Windows Server 2003 64bits Edition


避免内存溢出的几点要素

如果要创建数组,请确保其大小正确。

确保有足够的内存用于内部用途和新的托管对象。

如果您正在 .NET Compact Framework 上进行编程,当没有足够的内存可用于内部用途或新的托管对象时,公共语言运行库会引发此异常。要避免此异常,应避免编写占用 64KB 或更多内存的大方法。

过多的托管内存使用量通常由以下因素造成:

  • 将大型数据集读入内存中。
  • 创建过多的缓存条目。
  • 上载或下载大文件。
  • 在分析文件时过多地使用正则表达式或字符串。
  • 过多的视图状态。
  • 会话状态中有过多的数据或者会话过多。
  • 当对 COM 对象调用一个方法,并且该方法返回包含安全数组(大小不固定的数组)的用户定义类型时,可能引发此异常,并附带一条额外的消息“存储空间不足,无法完成此操作”。这是因为 .NET Framework 无法封送带有安全数组类型的结构字段。


一种不当使用字节数组导致内存溢出的情况举例

  1. public partial class _Default : System.Web.UI.Page
  2. {
  3.     protected void Page_Load(object sender, EventArgs e)
  4.     {
  5.         byte[] bytes = File.ReadAllBytes("D:\toClient.xls");//toClient.xls 大小为20M
  6.         Response.BinaryWrite(bytes);
  7.     }
  8. }
复制代码

上面的程序如果所输出的文件特别大的话,有可能会直接报:System.OutOfMemoryException。正确的做法是把文件的字节流分段输出,其实asp.net有现成的方法Response.WriteFile(filePath)就是这么做的。

如下是正确的写法:

  1. Response.ContentType = "application/octet-stream";
  2. Response.AddHeader("Content-Disposition", "attachment; filename=" + HttpUtility.UrlEncode(downloadName, System.Text.Encoding.UTF8));
  3. Response.WriteFile("D:\toClient.xls");
  4. Response.Flush();
  5. Response.End();
复制代码
当asp.net出现内存溢出时,一种简单的处理方法是马上回收应用程序池。但是这样并没有彻底解决问题。

创建Image类型时出现内存溢出(System.OutOfMemoryException)

错误代码: System.Drawing.Image myimg=System.Drawing.Image.FromFile(file.FullName);

当打开的文件不是图像文件时会引发的异常:

360截图20190314214454165.jpg

MSDN:如果文件没有有效的图像格式,或者如果 GDI+ 不支持文件的像素格式,则此方法将引发 OutOfMemoryException 异常。

这样的异常信息容易让人误解。

<processModel> 元素

在 Internet 信息服务 (IIS) Web 服务器上配置 ASP.NET 进程模型设置。只能在 Machine.config 文件中设置 <processModel> 节,并且该节影响服务器上运行的所有 ASP.NET 应用程序。

警告 有关此元素的信息,请阅读“注释”部分。

配置结构的示例:

  1. <processModel enable="true|false"
  2.               timeout="hrs:mins:secs|Infinite"
  3.               idleTimeout="hrs:mins:secs|Infinite"
  4.               shutdownTimeout="hrs:mins:secs|Infinite"
  5.               requestLimit="hrs:mins:secs|Infinite"
  6.               requestQueueLimit="num|Infinite"
  7.               restartQueueLimit="num|Infinite"
  8.               memoryLimit="percent"
  9.               cpuMask="num"
  10.               webGarden="true|false"
  11.               userName="username"
  12.               password="password"
  13.               logLevel="All|None|Errors"
  14.               clientConnectedCheck="hrs:mins:secs|Infinite"
  15.               responseDeadlockInterval="hrs:mins:secs|Infinite"
  16.               responseRestartDeadlockInterval="hrs:mins:secs|Infinite"
  17.               comAuthenticationLevel="Default|None|Connect|Call|
  18.                                       Pkt|PktIntegrity|PktPrivacy"
  19.               comImpersonationLevel="Default|Anonymous|Identify|
  20.                                      Impersonate|Delegate"
  21.               maxWorkerThreads="num"
  22.               maxIoThreads="num"/>
复制代码
注释

托管代码配置系统并不读取 <processModel> 配置设置。而是由非托管 DLL aspnet_isapi.dll 直接读取。重新启动 IIS 后,本节的更改才会生效。

如果在域控制器上安装 ASP.NET,必须采取特殊的步骤,否则安装无法正常进行。详细信息,请参阅位于 http://support.microsoft.com 的 Microsoft 知识库中的文章 CHS315158“ASP.NET 在域控制器上不能使用默认 ASPNET 帐户”。

当 ASP.NET 在 IIS 版本 6 本机模式下运行时,使用 IIS 6 进程模型并且忽略 <processModel> 节中的设置。要配置进程标识、回收或其他进程模型值,请使用 Internet 服务管理器用户界面为应用程序配置 IIS 工作进程。

时间值的格式为“时:分:秒”。如果只给出单个数字而没有冒号,则假定该值为分钟数;因此 timeout="4" 等同于 timeout="00:04:00"。

如果 ASP.NET 应用程序导致 ASP.NET 工作进程(Windows 2000 和 Windows XP Professional 上的 Aspnet_wp.exe 以及 Windows Server 2003 上的 W3wp.exe)重新启动,并给出一条错误消息,指示重新启动是由于怀疑的死锁状态造成的,则应该增加 responseDeadlockInterval 设置。

在注册表中存储用户名和密码

将用户名和密码存储在注册表中

要加密用户名和密码并将它们存储在注册表中,请按如下方式设置 userName 和 password。

userName="registry:HKLM\Software\AspNetProcess,Name"

password="registry:HKLM\Software\AspNetProcess,Pwd"

关键字 registry 后面、逗号前面的字符串部分表示 ASP.NET 所打开的注册表项的名称。逗号后面的部分包含一个字符串值名,ASP.NET 将从中读取凭据。逗号是必需的,凭据必须存储在 HKLM 配置单元中。如果配置格式有误,则 ASP.NET 将不启动工作进程,并随后出现当前帐户创建失败代码的路径。

凭据必须采用 REG_BINARY 格式,其中包含对 Windows API 函数 CryptProtectData 调用的输出结果。您可以用 ASP.NET设置注册表控制台应用程序 (Aspnet_setreg.exe) 创建加密凭据并将其存储在注册表中,该应用程序使用 CryptProtectData 完成加密。要下载 Aspnet_setreg.exe 以及 Visual C++ 源代码和帮助,请访问网站 www.asp.net 并搜索“aspnet_setreg”。

您应该对存储加密凭据的注册表项配置访问权限,以便只对 Administrators 和 SYSTEM 提供访问。因为该注册表项将由作为 SYSTEM 运行的 ASP.NET 进程读取,您应该设置下列权限:

Administrators:F

SYSTEM:F

CREATOR OWNER:F

ProcessAccount:R

这将提供两道防线来保护数据:

ACL 权限要求访问数据的标识为 Administrator。
攻击者必须在服务器上运行代码 (CryptUnprotectData) 以便恢复帐户的凭据。

示例

以下示例指定几个 <processModel> 配置设置。

  1. <configuration>
  2.    <system.web>
  3.       <processModel
  4.          enable="true"
  5.          timeout="15"
  6.          idleTimeout="25"
  7.          shutdownTimeout="5"
  8.          requestLimit="1000"
  9.          requestQueueLimit="500"
  10.          responseDeadlockInterval="00:03:00"              
  11.          responseRestartDeadlockInterval="Infinite"
  12.          memoryLimit="20"
  13.          webGarden="true"
  14.          maxWorkerThreads="25"
  15.          maxIoThreads="25"/>
  16.    </system.web>
  17. </configuration>
复制代码
以下示例指定将加密的用户名和密码存储在注册表用户定义的项 AspNetProcess 下面。

  1. <configuration>
  2.    <system.web>
  3.       <processModel>
  4.          userName="registry:HKLM\Software\AspNetProcess,Name"
  5.          password="registry:HKLM\Software\AspNetProcess,Pwd"
  6.       </processModel>
  7.    </system.web>
  8. </configuration>
复制代码
要求

  • 包含在:<system.web> 中
  • Web 平台:IIS 5.0、IIS 5.1、IIS 6.0
  • 配置文件:Machine.config、Web.config
  • 配置节处理程序:System.Web.Configuration.ProcessModelConfigurationHandler


http://doc.51windows.net/iismmc/ ... essmodelelement.htm





上一篇:C#判断上传文件是否是图片,防止木马上传
下一篇:Python从入门到项目实践(全彩版)
码农网,只发表在实践过程中,遇到的技术难题,不误导他人。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

免责声明:
码农网所发布的一切软件、编程资料或者文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。

Mail To:help@itsvse.com

QQ|Archiver|手机版|小黑屋|架构师 ( 鲁ICP备14021824号-2 )|网站地图

GMT+8, 2019-5-27 08:12

Powered by Discuz! X3.4

© 2001-2014 Comsenz Inc.

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