添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
public ref class OutOfMemoryException : Exception
public ref class OutOfMemoryException : SystemException
public class OutOfMemoryException : Exception
public class OutOfMemoryException : SystemException
[System.Serializable]
public class OutOfMemoryException : SystemException
[System.Serializable]
[System.Runtime.InteropServices.ComVisible(true)]
public class OutOfMemoryException : SystemException
type OutOfMemoryException = class
    inherit Exception
type OutOfMemoryException = class
    inherit SystemException
[<System.Serializable>]
type OutOfMemoryException = class
    inherit SystemException
[<System.Serializable>]
[<System.Runtime.InteropServices.ComVisible(true)>]
type OutOfMemoryException = class
    inherit SystemException
Public Class OutOfMemoryException
Inherits Exception
Public Class OutOfMemoryException
Inherits SystemException
Object
OutOfMemoryException OutOfMemoryException 使用 HRESULT COR_E_OUTOFMEMORY ,其值为 0x8007000E。

有关实例的初始属性值的列表 OutOfMemoryException ,请参阅 OutOfMemoryException 构造函数。

继承 Data 属性的值始终 null 为 。

异常 OutOfMemoryException 有两个主要原因:

  • 您正尝试扩展 StringBuilder 对象超出其 StringBuilder.MaxCapacity 属性定义的长度。

  • 公共语言运行时无法分配足够的连续内存来成功执行操作。 需要内存分配的任何属性分配或方法调用都可能会引发此异常。 有关异常原因 OutOfMemoryException 的详细信息,请参阅博客文章 “内存不足”不引用物理内存

    这种类型的 OutOfMemoryException 异常表示灾难性故障。 如果选择处理异常,则应包含一个 catch 块,该块调用 Environment.FailFast 方法以终止应用并将条目添加到系统事件日志,如以下示例所示。

    using System;
    public class Example
       public static void Main()
          try {
             // Outer block to handle any unexpected exceptions.
             try {
                string s = "This";
                s = s.Insert(2, "is ");
                // Throw an OutOfMemoryException exception.
                throw new OutOfMemoryException();
             catch (ArgumentException) {
                Console.WriteLine("ArgumentException in String.Insert");
             // Execute program logic.
          catch (OutOfMemoryException e) {
             Console.WriteLine("Terminating application unexpectedly...");
             Environment.FailFast(String.Format("Out of Memory: {0}",
                                                e.Message));
    // The example displays the following output:
    //        Terminating application unexpectedly...
    
    open System
        // Outer block to handle any unexpected exceptions.
            let s = "This"
            let s = s.Insert(2, "is ")
            // Throw an OutOfMemoryException exception.
            raise (OutOfMemoryException())
        | :? ArgumentException ->
            printfn "ArgumentException in String.Insert"
        // Execute program logic.
    with :? OutOfMemoryException as e ->
        printfn "Terminating application unexpectedly..."
        Environment.FailFast $"Out of Memory: {e.Message}"
    // The example displays the following output:
    //        Terminating application unexpectedly...
    
    Module Example
       Public Sub Main()
             ' Outer block to handle any unexpected exceptions.
                Dim s As String = "This"
                s = s.Insert(2, "is ")
                ' Throw an OutOfMemoryException exception.
                Throw New OutOfMemoryException()
             Catch e As ArgumentException
                Console.WriteLine("ArgumentException in String.Insert")
             End Try
             ' Execute program logic.
          Catch e As OutOfMemoryException
             Console.WriteLine("Terminating application unexpectedly...")
             Environment.FailFast(String.Format("Out of Memory: {0}",
                                                e.Message))
          End Try
       End Sub
    End Module
    ' The example displays the following output:
    '       Terminating application unexpectedly...
    

    引发异常的一些条件以及可以采取的消除异常的操作包括:

    你正在调用 StringBuilder.Insert 方法。

    您试图增加 对象的长度 StringBuilder 超出其 StringBuilder.MaxCapacity 属性指定的大小。 下面的示例演示 OutOfMemoryException 当示例尝试插入将导致对象的 属性超出其最大容量的字符串时调用 方法引发 StringBuilder.Insert(Int32, String, Int32)Length 异常。

    using System;
    using System.Text;
    public class Example
       public static void Main()
          StringBuilder sb = new StringBuilder(15, 15);
          sb.Append("Substring #1 ");
          try {
             sb.Insert(0, "Substring #2 ", 1);
          catch (OutOfMemoryException e) {
             Console.WriteLine("Out of Memory: {0}", e.Message);
    // The example displays the following output:
    //    Out of Memory: Insufficient memory to continue the execution of the program.
    
    open System
    open System.Text
    let sb = StringBuilder(15, 15)
    sb.Append "Substring #1 "
    |> ignore
        sb.Insert(0, "Substring #2 ", 1)
        |> ignore
    with :? OutOfMemoryException as e ->
        printfn $"Out of Memory: {e.Message}"
    // The example displays the following output:
    //    Out of Memory: Insufficient memory to continue the execution of the program.
    
    Imports System.Text
    Module Example
       Public Sub Main()
          Dim sb As New StringBuilder(15, 15)
          sb.Append("Substring #1 ")
             sb.Insert(0, "Substring #2 ", 1)
          Catch e As OutOfMemoryException
             Console.WriteLine("Out of Memory: {0}", e.Message)
          End Try
       End Sub
    End Module
    ' The example displays the following output:
    '   Out of Memory: Insufficient memory to continue the execution of the program.
    

    可以执行以下任一操作来解决此错误:

  • 将对构造函数的 StringBuilder.StringBuilder(Int32, Int32) 调用替换为调用任何其他 StringBuilder 构造函数重载。 对象的最大容量 StringBuilder 将设置为其默认值,即 Int32.MaxValue

    StringBuilder.StringBuilder(Int32, Int32)使用maxCapacity足以容纳对象的任何扩展StringBuilder的值调用构造函数。

    应用作为 32 位进程运行。

    在 32 位系统上,32 位进程最多可以分配 2GB 的虚拟用户模式内存,在 64 位系统上最多分配 4GB 虚拟用户模式内存。 这会使公共语言运行时在需要大量分配时更难分配足够的连续内存。 相比之下,64 位进程最多可以分配 8TB 的虚拟内存。 若要解决此异常,请重新编译应用以面向 64 位平台。 有关在 Visual Studio 中面向特定平台的信息,请参阅 如何:将项目配置为面向平台

    你的应用正在泄漏非托管资源

    尽管垃圾回收器能够释放分配给托管类型的内存,但它不会管理分配给非托管资源的内存,例如操作系统句柄 (包括文件句柄、内存映射文件句柄、管道、注册表项和等待句柄,) 和内存块直接由 Windows API 调用分配或通过调用内存分配函数(如 ) malloc分配的内存块。 使用非托管资源的类型实现 IDisposable 接口。

    如果要使用使用非托管资源的类型,则应确保在使用完后调用其 IDisposable.Dispose 方法。 (某些类型还实现 Close 与 method 函数相同的 Dispose 方法。) 有关详细信息,请参阅 使用实现 IDisposable 的对象 主题。

    如果已创建使用非托管资源的类型,请确保已实现 Dispose 模式,并在必要时提供终结器。 有关详细信息,请参阅 实现 Dispose 方法和Object.Finalize

    尝试在 64 位进程中创建大型数组

    默认情况下,.NET Framework 中的公共语言运行时不允许大小超过 2GB 的单个对象。 若要替代此默认值,可以使用 <gcAllowVeryLargeObjects> 配置文件设置来启用总大小超过 2 GB 的数组。 在 .NET Core 上,默认启用对大于 2 GB 的数组的支持。

    你正在处理大量数据集 (,例如内存中) 数组、集合或数据库数据集。

    当驻留在内存中的数据结构或数据集变得太大,以至于公共语言运行时无法为其分配足够的连续内存时,会出现 OutOfMemoryException 异常。

    若要防止 OutOfMemoryException 出现异常,必须修改应用程序,以便内存中驻留的数据更少,或者将数据划分为需要较小内存分配的段。 例如:

  • 如果要从数据库中检索所有数据,然后在应用中对其进行筛选以最大程度地减少到服务器的行程,则应修改查询以仅返回应用所需的数据子集。 使用大型表时,多个查询几乎总是比检索单个表中的所有数据然后对其进行操作更高效。

  • 如果要执行用户动态创建的查询,则应确保查询返回的记录数受到限制。

  • 如果使用大型数组或其他集合对象,其大小会导致 OutOfMemoryException 异常,则应修改应用程序以处理子集中的数据,而不是一次性处理所有这些数据。

    以下示例获取一个由 2 亿个浮点值组成的数组,然后计算它们的平均值。 该示例的输出显示,由于该示例在计算平均值之前将整个数组存储在内存中, OutOfMemoryException 因此会引发 。

    using System;
    using System.Collections.Generic;
    public class Example
       public static void Main()
          Double[] values = GetData();
          // Compute mean.
          Console.WriteLine("Sample mean: {0}, N = {1}",
                            GetMean(values), values.Length);
       private static Double[] GetData()
          Random rnd = new Random();
          List<Double> values = new List<Double>();
          for (int ctr = 1; ctr <= 200000000; ctr++) {
             values.Add(rnd.NextDouble());
             if (ctr % 10000000 == 0)
                Console.WriteLine("Retrieved {0:N0} items of data.",
                                  ctr);
          return values.ToArray();
       private static Double GetMean(Double[] values)
          Double sum = 0;
          foreach (var value in values)
             sum += value;
          return sum / values.Length;
    // The example displays output like the following:
    //    Retrieved 10,000,000 items of data.
    //    Retrieved 20,000,000 items of data.
    //    Retrieved 30,000,000 items of data.
    //    Retrieved 40,000,000 items of data.
    //    Retrieved 50,000,000 items of data.
    //    Retrieved 60,000,000 items of data.
    //    Retrieved 70,000,000 items of data.
    //    Retrieved 80,000,000 items of data.
    //    Retrieved 90,000,000 items of data.
    //    Retrieved 100,000,000 items of data.
    //    Retrieved 110,000,000 items of data.
    //    Retrieved 120,000,000 items of data.
    //    Retrieved 130,000,000 items of data.
    //    Unhandled Exception: OutOfMemoryException.
    
    open System
    let getData () =
        let rnd = Random()
        [|  for i = 1 to 200000000 do
                rnd.NextDouble()
                if i % 10000000 = 0 then
                    printfn $"Retrieved {i:N0} items of data." |]
    let getMean values =
        let sum = Array.sum values
        sum / float values.Length
    let values = getData ()
    // Compute mean.
    printfn $"Sample mean: {getMean values}, N = {values.Length}"
    // The example displays output like the following:
    //    Retrieved 10,000,000 items of data.
    //    Retrieved 20,000,000 items of data.
    //    Retrieved 30,000,000 items of data.
    //    Retrieved 40,000,000 items of data.
    //    Retrieved 50,000,000 items of data.
    //    Retrieved 60,000,000 items of data.
    //    Retrieved 70,000,000 items of data.
    //    Retrieved 80,000,000 items of data.
    //    Retrieved 90,000,000 items of data.
    //    Retrieved 100,000,000 items of data.
    //    Retrieved 110,000,000 items of data.
    //    Retrieved 120,000,000 items of data.
    //    Retrieved 130,000,000 items of data.
    //    Unhandled Exception: OutOfMemoryException.
    
    Imports System.Collections.Generic
    Module Example
       Public Sub Main()
          Dim values() As Double = GetData()
          ' Compute mean.
          Console.WriteLine("Sample mean: {0}, N = {1}",
                            GetMean(values), values.Length)
       End Sub
       Private Function GetData() As Double()
          Dim rnd As New Random()
          Dim values As New List(Of Double)()
          For ctr As Integer = 1 To 200000000
             values.Add(rnd.NextDouble)
             If ctr Mod 10000000 = 0 Then
                Console.WriteLine("Retrieved {0:N0} items of data.",
             End If
          Return values.ToArray()
       End Function
       Private Function GetMean(values() As Double) As Double
          Dim sum As Double = 0
          For Each value In values
             sum += value
          Return sum / values.Length
       End Function
    End Module
    ' The example displays output like the following:
    '    Retrieved 10,000,000 items of data.
    '    Retrieved 20,000,000 items of data.
    '    Retrieved 30,000,000 items of data.
    '    Retrieved 40,000,000 items of data.
    '    Retrieved 50,000,000 items of data.
    '    Retrieved 60,000,000 items of data.
    '    Retrieved 70,000,000 items of data.
    '    Retrieved 80,000,000 items of data.
    '    Retrieved 90,000,000 items of data.
    '    Retrieved 100,000,000 items of data.
    '    Retrieved 110,000,000 items of data.
    '    Retrieved 120,000,000 items of data.
    '    Retrieved 130,000,000 items of data.
    '    Unhandled Exception: OutOfMemoryException.
    

    以下示例通过处理传入数据而不将整个数据集存储在内存中来消除 OutOfMemoryException 此异常,如有必要,将数据序列化为文件以允许进一步处理 (示例中注释掉这些行,因为在这种情况下,它们将生成一个大小大于 1GB) 的文件,并将计算的平均值和事例数返回到调用例程。

    using System;
    using System.IO;
    public class Example
       public static void Main()
          Tuple<Double, long> result = GetResult();
          Console.WriteLine("Sample mean: {0}, N = {1:N0}",
                            result.Item1, result.Item2);
       private static Tuple<Double, long> GetResult()
          int chunkSize = 50000000;
          int nToGet = 200000000;
          Random rnd = new Random();
          // FileStream fs = new FileStream(@".\data.bin", FileMode.Create);
          // BinaryWriter bin = new BinaryWriter(fs);
          // bin.Write((int)0);
          int n = 0;
          Double sum = 0;
          for (int outer = 0;
               outer <= ((int) Math.Ceiling(nToGet * 1.0 / chunkSize) - 1);
               outer++) {
             for (int inner = 0;
                  inner <= Math.Min(nToGet - n - 1, chunkSize - 1);
                  inner++) {
                Double value = rnd.NextDouble();
                sum += value;
                // bin.Write(value);
          // bin.Seek(0, SeekOrigin.Begin);
          // bin.Write(n);
          // bin.Close();
          return new Tuple<Double, long>(sum/n, n);
    // The example displays output like the following:
    //    Sample mean: 0.500022771458399, N = 200,000,000
    
    open System
    // open System.IO
    let getResult () =
        let chunkSize = 50000000
        let nToGet = 200000000
        let rnd = Random()
        // use fs = new FileStream(@".\data.bin", FileMode.Create)
        // use bin = new BinaryWriter(fs)
        // bin.Write 0
        let mutable n = 0
        let mutable sum = 0.
        for _ = 0 to int (ceil (nToGet / chunkSize |> float) - 1.) do
            for _ = 0 to min (nToGet - n - 1) (chunkSize - 1) do
                let value = rnd.NextDouble()
                sum <- sum + value
                n <- n + 1
                // bin.Write(value)
        // bin.Seek(0, SeekOrigin.Begin) |> ignore
        // bin.Write n
        sum / float n, n
    let mean, n = getResult ()
    printfn $"Sample mean: {mean}, N = {n:N0}"
    // The example displays output like the following:
    //    Sample mean: 0.500022771458399, N = 200,000,000
    
    Imports System.IO
    Module Example
       Public Sub Main()
          Dim result As Tuple(Of Double, Long) = GetResult()
          Console.WriteLine("Sample mean: {0}, N = {1:N0}",
                            result.Item1, result.Item2)
       End Sub
       Private Function GetResult As Tuple(Of Double, Long)
          Dim chunkSize As Integer = 50000000
          Dim nToGet As Integer = 200000000
          Dim rnd As New Random()
    '       Dim fs As New FileStream(".\data.bin", FileMode.Create)
    '       Dim bin As New BinaryWriter(fs)
    '       bin.Write(CInt(0))
          Dim n As Integer
          Dim sum As Double
          For outer As Integer = 0 To CInt(Math.Ceiling(nToGet/chunkSize) - 1)
             For inner = 0 To Math.Min(nToGet - n - 1, chunkSize - 1)
                Dim value As Double = rnd.NextDouble()
                sum += value
                n += 1
    '            bin.Write(value)
    '       bin.Seek(0, SeekOrigin.Begin)
    '       bin.Write(n)
    '       bin.Close()
          Return New Tuple(Of Double, Long)(sum/n, n)
       End Function
    End Module
    ' The example displays output like the following:
    '   Sample mean: 0.500022771458399, N = 200,000,000
                  重复串联大型字符串。

    由于字符串是不可变的,因此每个字符串串联操作都会创建一个新字符串。 小字符串或少量串联操作的影响可以忽略不计。 但对于大型字符串或大量串联操作,字符串串联可能会导致大量内存分配和内存碎片、性能不佳以及可能 OutOfMemoryException 异常。

    连接大型字符串或执行大量串联操作时,应使用 StringBuilder 类而不是 String 类。 操作完字符串后,通过调用 StringBuilder.ToString 方法将 StringBuilder 实例转换为字符串。

    在内存中固定大量对象。

    长时间在内存中固定大量对象可能会使垃圾回收器难以分配连续的内存块。 如果已将大量对象固定到内存中,例如使用 fixed C# 中的 语句或通过调用 GCHandle.Alloc(Object, GCHandleType) 句柄类型为 的方法 GCHandleType.Pinned,则可以执行以下操作来解决 OutOfMemoryException 异常。

  • 评估每个对象是否确实需要固定,

  • 确保尽快取消固定每个对象。

  • 确保每次调用 GCHandle.Alloc(Object, GCHandleType) 方法以固定内存时,都会对 方法进行相应的调用 GCHandle.Free ,以取消固定该内存。

    以下 Microsoft 中间 (MSIL) 指令引发 OutOfMemoryException 异常:

    newarr
  • newobj
  •