2013-08-04 27 views
0

编译我有一个正在运行的内存只有当我与以下异常内存溢出异常时,应用在86

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) 

的内存消耗在Windows上运行它的x86 7模式下的.NET应用程序大约是400 mb,GDI对象在1500左右消耗(我已经增加了注册表中的这些限制,所以不应该有任何问题需要大约10000)。

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

即使我的内存高达2 GB,我从来没有在x64模式下出现异常。

请帮我理解我在达到的内存方面的限制。

+4

回溯没有说任何关于内存问题 - 它说“参数无效”。 –

+0

以及您处理图像时,在WPF中使用大或高分辨率图像时,这会非常复杂。我想这背后的图像是一个相当大的决议? WPF总是有问题 – Venson

+0

它似乎是'ArgumentException' –

回答

7

GDI +异常相当差,这是由于它早在.NET出现之前就开发出来的,并且只有一些错误代码。在这样的情况下,内存实际上很可能是问题所在。 “参数无效”是GDI +在为什么无法加载图像的原因。其中可能是因为图像文件包含垃圾,反过来会让它尝试分配太多的内存。在很多情况下选择不当。

32位进程拥有2千兆字节的虚拟内存,无论您的计算机具有多少内存。地址空间需要由代码和数据共享。它的块将被CLR,抖动,框架程序集,程序集,程序的jitted代码以及.NET程序使用的大约10个不同的堆占用,包括GC堆。这些块的分配倾向于通过地址空间分散。当你分配内存的时候,你会从这些已经存在的块之间的可用空洞中获取另一块。

位图的一个大问题是它们可能相当于。他们需要适应一个可用的洞。随着程序分配和释放内存,这些漏洞会逐渐变小。一个称为“地址空间碎片”的问题。当你的程序第一次启动时,你通常可以找到〜650兆字节的漏洞。但是当你的程序运行了一段时间后,这种情况迅速下降。长期运行的程序的危险区域约为90兆字节。

当没有可用的空洞足以容纳位图时,您的程序会发生此例外炸弹。这会在您的程序消耗完所有可用虚拟内存之前发生。你可以做很多小的分配,但不是一个大的分配。

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

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