创建数组时出现 System OutOfMemoryException

Posted

技术标签:

【中文标题】创建数组时出现 System OutOfMemoryException【英文标题】:SystemOutOfMemoryException When Creating Array 【发布时间】:2014-09-30 14:45:03 【问题描述】:

我在创建数组时收到SystemOutOfMemoryException。然而我的数组does notlength 超过了Int32.MaxValue

这是代码(请不要判断代码,它不是我的代码至少 7 岁)

Dim myFileToUpload As New IO.FileInfo(IO.Path.Combine(m_Path, filename))
Dim myFileStream As IO.FileStream
Try
    myFileStream = myFileToUpload.OpenRead
    Dim bytes As Long = myFileStream.Length //(Length is roughly 308 million)
    If bytes > 0 Then
        Dim data(bytes - 1) As Byte // OutOfMemoryException is caught here
        myFileStream.Read(data, 0, bytes)
        objInfo.content = data
    End If
Catch ex As Exception
    Throw ex
Finally
    myFileStream.Close()
End Try

根据这个问题“SO Max Size of .Net Arrays”和这个问题“Maximum lenght of an array”,最大长度是2,147,483,647 elements Or Int32.MaxValue,而maximum size2 GB

所以我的总数 length of my array is well within the limits(3.08 亿 my size is way smaller 然后显示 2 GB(文件大小为 298 mb)。

问题: 所以我的问题是,关于数组还有什么可能导致MemoryOutOfMemoryException

注意:对于那些想知道服务器仍然有一些 10gb 可用内存空间的人

注意 2: 在dude's advice 之后,我在几次运行中监控了 GDI 对象的数量。进程本身永远不会超过 1500 个对象的计数。

【问题讨论】:

一个OutOfMemoryException与数组长度无关。 @TimSchmelter 完全正确 发生在该特定行的原因是什么? 您的应用程序中的data 是什么? @dude 将尝试监控 GDI 对象的数量。我会在这里发布结果。 【参考方案1】:

byte 数组是一个序列中的字节。这意味着您必须分配如此多的内存,因为您的数组是一个块中的长度。如果您的内存碎片比系统无法分配内存,即使您有 X GB 内存可用。

例如,在我的机器上,我不能在一个数组中分配超过 908 000 000 个字节,但如果它存储在更多数组中,我可以毫无问题地分配 100 * 90 800 000:

// alocation in one array

byte[] toBigArray = new byte[908000000]; //doesn't work (6 zeroes after 908)

// allocation in more arrays
byte[][] a=new byte[100][]; 

for (int i = 0 ; i<a.Length;i++) // it works even there is 10x more memory needed than before

    a[0] = new byte[90800000]; // (5 zeroes after 908) 

【讨论】:

我最近读到了类似的东西(我的内存分配太大了)。类似于数组的东西需要内存的连续部分。我现在正在尝试以块的形式导入文件。希望能解决问题 是的,放弃吧。您的系统根本无法分配数组...也就是说您将其分配给另一个整体的对象...可能会遇到同样的问题... 是的。看起来我正在看相当多的代码调整“Sigh【参考方案2】:

您可以在原地读取/写入数据,而无需先加载到内存中。如果您不想更改原始文件,只需System.IO.File.Copy 文件即可。

Dim strFilename As String = "C:\Junk\Junk.bmp" 'a big file
Using fs As New FileStream(strFilename, FileMode.Open)
  Dim lngLength As Long = fs.Length
  fs.Seek(lngLength \ 2, SeekOrigin.Begin)
  For l As Long = 0 To lngLength \ 4
    Dim b As Byte = CByte(fs.ReadByte())
    b = Not b
    fs.WriteByte(b)
  Next
End Using
MsgBox("Finished!")

另请参阅:http://msdn.microsoft.com/query/dev11.query?appId=Dev11IDEF1&l=EN-US&k=k%28System.IO.FileStream.WriteByte%29;k%28TargetFrameworkMoniker-.NETFramework

【讨论】:

非常有价值的解决方案(因此获得了支持)。然而了解程序的上下文,这将导致相当大的调整。把它放在另一个上不需要太多的改变(尽管仍然不能被低估)。 你应该在块中缓冲和读取文件,否则它会非常慢。例如,您可以使用 BufferedStream 包装器

以上是关于创建数组时出现 System OutOfMemoryException的主要内容,如果未能解决你的问题,请参考以下文章

将数组移交给 C# 中动态加载的 C++ DLL 时出现 System.AccessViolationException

创建 websocket 连接时出现 System.Net.Sockets.SocketException

调用 WebService 方法时出现错误 System.InvalidOperationException

创建非常大的numpy数组时出现MemoryError [重复]

在程序文件下运行 .exe 时出现 System.UnauthorizedAccessException

创建对象数组时出现NullPointerException [重复]