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

本文关键字:内存不足 异常 应用程序 x86 编译 | 更新日期: 2023-09-27 18:26:12

我有一个.NET应用程序,只有当我在Windows7模式下以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)

内存消耗大约是400mb,GDI对象消耗大约1500(我已经在注册表中增加了这些对象的限制,所以达到10000左右应该没有任何问题)。

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

我在x64模式下从来没有例外,即使我的内存高达2GB。

请帮助我理解我的记忆力达到了哪个极限。

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

GDI+异常相当糟糕,这是由于它早在.NET出现之前就已经开发出来了,并且只有一些错误代码。在这种情况下,实际上很可能是内存问题"参数无效";是GDI+双关语解释了图像无法加载的原因。可能是,因为图像文件包含垃圾,这反过来会让它试图分配太多内存。在大量情况下选择不当。

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

位图的一个大问题是它们可能非常大。它们需要装在一个可用的洞里。随着程序分配和释放内存,这些漏洞往往会随着时间的推移而变小。一个叫做";地址空间碎片";。程序刚启动时,通常会发现一个约650兆字节的漏洞。但当你的程序运行了一段时间后,这种情况就会迅速下降。一个长时间运行的程序的危险区大约在90兆字节左右。

当没有足够大的洞来容纳位图时,你的程序会抛出这个异常。这将在程序消耗完所有可用虚拟内存之前很久发生。你可以进行许多小的分配,但不能进行一个大的分配。

这个问题有一个简单的解决办法。将EXE项目上的目标平台设置更改为AnyCPU,关闭";优选32位";适用于VS2012及更高版本。在64位操作系统上,程序的虚拟机地址空间要大得多,可能达到1TB。你不能跑出足够大的洞。