我有一个WPF桌面应用程序崩溃,但有以下异常:
System.Data.SqlServerCe.SqlCeException(0x80004005):运行SQL Server的设备上没有足够的内存
但是,崩溃时的内存值对我来说有点不清楚:
顺便说一句。 Current Process值取自C#Process类。 ComputerInfo值取自VB.NET ComputerInfo类。
我的应用程序是使用(x86)配置编译的。该过程在Windows 7 64位计算机上运行。
我看到可用虚拟内存为166MB,看起来很低。
当VB.NET ComputerInfo类报告有大量AvailablePhysicalMemory时,进程如何崩溃?
高电流和峰值工作设置表明某处可能存在内存泄漏,但是当有足够的可用内存时,我仍然无法理解崩溃的原因。
答案 0 :(得分:7)
您认为物理记忆具有任何相关性是您混淆的根本原因。请记住,考虑内存的正确方法是进程内存是磁盘空间。物理内存只是磁盘顶部的快速缓存。再次强调一下:如果你的物理内存耗尽,那么你的机器就会变慢。它不会给出内存不足错误。
相关资源是虚拟地址空间,而不是内存。每32位进程只能获得4GB的虚拟地址空间,并且为使用操作系统保留2GB的虚拟地址空间。假设您剩下166 MB的虚拟地址空间,并将其分成四个块,每个块42 MB。如果有50MB的请求,则无法满足该请求。不幸的是,你得到的错误是“内存不足”,而不是“超出虚拟地址空间”,这将是一个更准确的错误消息。
您的问题的解决方案是:(1)为每个进程分配少于2GB的用户内存,(2)实现您自己的系统,用于将内存映射到虚拟地址空间和从虚拟地址空间出来,或者(3)使用64位具有大量可用虚拟地址空间的进程。
答案 1 :(得分:1)
每个32位(因为TotalVirtualMemory:2047 MB,你有32位进程)只能处理最多2GB的内存,无论可用的物理内存如何。
答案 2 :(得分:1)
OutOfMemoryException
可能是由许多事情引起的。
当您的应用程序在Gen0托管堆或大对象堆中没有足够的空间来处理新分配时,可能会导致此错误。这是一种罕见的情况,但通常会在堆碎片太多而无法允许新的分配(有时是相当小的大小!)时发生。在Gen0中,这可能是由于过度使用固定对象(当使用非托管代码处理互操作时);在LOH中,这曾经是一个常见的问题,但在更高版本的.NET中出现的频率要低得多。值得注意的是,SqlCe访问将包括非托管代码;我没有听说过这方面的任何重大问题,但您使用SqlCe类可能会导致问题。
或者,它可能是一个虚拟内存问题 - 考虑到你发布的数据,这似乎很合理。 Eric Lippert有一篇关于此类问题的好文章here。如果您的应用程序试图将内存页写入磁盘以便它可以在内存中保留其他内容,那么您很可能会看到异常,因为您的VM非常有限。