在x86中编译应用程序时出现内存不足异常

时间:2013-08-04 10:24:55

标签: c# .net

我有一个.NET应用程序,只有当我在Windows 7模式下在x86中运行时才会耗尽内存,但有以下异常

8/4/2013 11:36:52 AM: Main application context(1) CriticalError:    Exception in Application context Run: Main application context : Parameter is not valid.   at System.Drawing.Image.get_Width()
   at System.Drawing.Image.get_Size()
   at DevExpress.XtraBars.BarItem.IsSameSize(Image old, Image newImage)
   at DevExpress.XtraBars.BarItem.set_Glyph(Image value)
   at NordicIT.Mark5.Module.DM.Editor.frmEditorRibbon..ctor()
   at NordicIT.Mark5.Module.DM.Editor.frmEditorRibbon..ctor(IEditFormForBOOptions editFormForBOOptions)
   at NordicIT.Mark5.Module.DM.Actions.TDMActions.<>c__DisplayClass19.<_DocumentTransmitProcess>b__17()
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)

内存消耗大约为400 MB,GDI对象消耗大约1500(我在注册表中增加了这些内容的限制,所以不应该有任何问题转到10000左右)。

当我在x86中的Windows server 2008 R2中运行相同的应用程序时我没有问题(它应该与Windows 7具有相同的内核),在x86的windows xp中也没问题。

即使我使用高达2 GB的内存,我也从未在x64模式下出现异常。

请帮助我了解我所达到的内存方面的限制。

1 个答案:

答案 0 :(得分:8)

GDI +异常相当差,因为它是在.NET出现之前很久就开发出来的,只有几个错误代码。在这种情况下,内存很可能是问题所在。 “参数无效”是GDI +因为无法加载图像而引发的。哪个可能因为图像文件包含垃圾,这反过来会让它尝试分配太多内存。在大量案件中选择不当。

无论您的计算机有多少RAM,32位进程都有2 GB的虚拟内存。地址空间需要由代码和数据共享。它的块将由CLR,抖动,框架程序集,程序集,程序的jitted代码以及.NET程序使用的大约10个不同的堆(包括GC堆)占用。这些块的分配往往分散在地址空间中。当您分配内存时,您将从这些现有块之间的可用孔中获取另一个块。

位图的一个大问题是它们可能非常。他们需要安装在可用的洞内。随着程序分配和释放内存,这些漏洞会随着时间的推移变小。一个叫做“地址空间碎片”的问题。程序首次启动时,通常可以找到大约650兆字节的漏洞。但是当你的程序运行了一段时间后,那很快就会从那里下降。长期运行程序的危险区域约为90兆字节,给予或接受。

如果没有可用的空洞足以容纳位图,那么您的程序就会遇到此异常。这将在您的程序消耗所有可用虚拟内存之前很久就会发生。你可以做很多小的分配而不是一个大分配。

此问题没有简单的解决方法。除了一个。将EXE项目中的目标平台设置更改为AnyCPU,关闭VS2012及更高版本的“首选32位”。在64位操作系统上,程序具有更大的VM地址空间,可以达到TB级。你根本无法用完足够大的洞。如果您遇到32位进程,则难以解决的问题是使用另一个进程来加载位图。这会给你带来另外2千兆字节的干净地址空间。不经常实用。

您可以使用SysInternals的VMMap实用程序来深入了解程序的VM使用情况。你可能找到一个在一个非常尴尬的地址加载的DLL,将一个大洞切成两个小洞。但是,不要抱有希望,你往往会完全淹没在数据中。

相关问题