OutOfMemoryException 类

定义

没有足够的内存继续执行程序时引发的异常。The exception that is thrown when there is not enough memory to continue the execution of a program.

public ref class OutOfMemoryException : SystemException
[System.Runtime.InteropServices.ComVisible(true)]
[System.Serializable]
public class OutOfMemoryException : SystemException
type OutOfMemoryException = class
    inherit SystemException
Public Class OutOfMemoryException
Inherits SystemException
继承
OutOfMemoryException
派生
属性

注解

OutOfMemoryException使用具有值COR_E_OUTOFMEMORY0x8007000E 的 HRESULT。OutOfMemoryException uses the HRESULT COR_E_OUTOFMEMORY, which has the value 0x8007000E.

有关实例的初始属性值的列表OutOfMemoryException,请参阅OutOfMemoryException构造函数。For a list of initial property values for an instance of OutOfMemoryException, see the OutOfMemoryException constructors.

备注

继承Data属性的值始终null为。The value of the inherited Data property is always null.

OutOfMemoryException异常有两个主要原因:An OutOfMemoryException exception has two major causes:

  • 你正试图展开一个StringBuilder超出其StringBuilder.MaxCapacity属性所定义的长度的对象。You are attempting to expand a StringBuilder object beyond the length defined by its StringBuilder.MaxCapacity property.

  • 公共语言运行时无法分配足够的连续内存来成功执行操作。The common language runtime cannot allocate enough contiguous memory to successfully perform an operation. 需要内存分配的任何属性赋值或方法调用都可能引发此异常。This exception can be thrown by any property assignment or method call that requires a memory allocation. 有关OutOfMemoryException异常原因的详细信息,请参阅博客文章"内存不足" 不引用物理内存For more information on the cause of the OutOfMemoryException exception, see the blog post "Out of Memory" Does Not Refer to Physical Memory.

    此类型的OutOfMemoryException异常表示灾难性故障。This type of OutOfMemoryException exception represents a catastrophic failure. 如果选择处理异常,则应包括一个catch Environment.FailFast调用方法的块以终止应用程序,并向系统事件日志中添加一个条目,如以下示例所示。If you choose to handle the exception, you should include a catch block that calls the Environment.FailFast method to terminate your app and add an entry to the system event log, as the following example does.

    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...
    
    Module Example
       Public Sub Main()
          Try
             ' Outer block to handle any unexpected exceptions.
             Try
                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...
    

引发异常的一些条件,以及可以采取哪些措施来消除异常,包括以下各项:Some of the conditions under which the exception is thrown and the actions you can take to eliminate it include the following:

正在调用StringBuilder.Insert方法。You are calling the StringBuilder.Insert method.

尝试增加StringBuilder对象的长度超出其StringBuilder.MaxCapacity属性指定的大小。You are attempting to increase the length of a StringBuilder object beyond the size specified by its StringBuilder.MaxCapacity property. 下面的示例演示当OutOfMemoryException示例尝试插入将导致对象的StringBuilder.Insert(Int32, String, Int32) Length属性超过其最大容量的字符串时,调用方法所引发的异常。The following example illustrates the OutOfMemoryException exception thrown by a call to the StringBuilder.Insert(Int32, String, Int32) method when the example tries to insert a string that would cause the object's Length property to exceed its maximum capacity.

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.
Imports System.Text

Module Example
   Public Sub Main()
      Dim sb As New StringBuilder(15, 15)
      sb.Append("Substring #1 ")
      Try
         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.

可以执行以下任一操作来解决该错误:You can do either of the following to address the error:

您的应用程序作为32位进程运行。Your app runs as a 32-bit process.

32位进程最多可以在32位系统上分配2GB 的虚拟用户模式内存,在64位系统上分配4GB 的虚拟用户模式内存。32-bit processes can allocate a maximum of 2GB of virtual user-mode memory on 32-bit systems, and 4GB of virtual user-mode memory on 64-bit systems. 这会使公共语言运行时在需要大量分配时更难分配足够的连续内存。This can make it more difficult for the common language runtime to allocate sufficient contiguous memory when a large allocation is needed. 与此相反,64位进程最多可分配8TB 的虚拟内存。In contrast, 64-bit processes can allocate up to 8TB of virtual memory. 若要解决此异常,请重新编译你的应用以面向64位平台。To address this exception, recompile your app to target a 64-bit platform. 有关在 Visual Studio 中面向特定平台的信息, 请参阅如何:将项目配置为面向平台For information on targeting specific platforms in Visual Studio, see How to: Configure Projects to Target Platforms.

应用正在泄漏非托管资源Your app is leaking unmanaged resources

虽然垃圾回收器能够释放分配给托管类型的内存,但它不管理分配给非托管资源(例如操作系统句柄)的内存(包括文件、内存映射文件、管道、注册表项和等待句柄的句柄)由 Windows API 调用或通过调用内存分配函数(如) malloc而直接分配的和内存块。Although the garbage collector is able to free memory allocated to managed types, it does not manage memory allocated to unmanaged resources such as operating system handles (including handles to files, memory-mapped files, pipes, registry keys, and wait handles) and memory blocks allocated directly by Windows API calls or by calls to memory allocation functions such as malloc. 使用非托管资源的类型实现IDisposable接口。Types that consume unmanaged resources implement the IDisposable interface.

如果你使用的是使用非托管资源的类型,则应确保在使用完IDisposable.Dispose该类型后调用其方法。If you are consuming a type that uses unmanaged resources, you should be sure to call its IDisposable.Dispose method when you have finished using it. (某些类型还实现Close了在函数Dispose中与方法相同的方法。)有关详细信息,请参阅使用实现 IDisposable 的对象主题。(Some types also implement a Close method that is identical in function to a Dispose method.) For more information, see the Using Objects That Implement IDisposable topic.

如果已创建使用非托管资源的类型,请确保已实现 Dispose 模式,并在必要时提供终结器。If you have created a type that uses unmanaged resources, make sure that you have implemented the Dispose pattern and, if necessary, supplied a finalizer. 有关详细信息,请参阅实现 Dispose 方法Object.FinalizeFor more information, see Implementing a Dispose method and Object.Finalize.

你正在尝试在64位进程中创建一个大型数组You are attempting to create a large array in a 64-bit process

默认情况下,.NET Framework 中的公共语言运行时不允许大小超过2GB 的单个对象。By default, the common language runtime in .NET Framework does not allow single objects whose size exceeds 2GB. 若要替代此默认值,可以使用 <gcAllowVeryLargeObjects >配置文件设置来启用总计大小超过 2 GB 的数组。To override this default, you can use the <gcAllowVeryLargeObjects> configuration file setting to enable arrays whose total size exceeds 2 GB. 在 .NET Core 中,默认情况下会启用支持大于 2 GB 的数组。On .NET Core, support for arrays of greater than 2 GB is enabled by default.

在内存中使用非常大的数据集(如数组、集合或数据库数据集)。You are working with very large sets of data (such as arrays, collections, or database data sets) in memory.

当内存中驻留的数据结构或数据集变得很大时,公共语言运行时无法为它们分配足够的连续内存时OutOfMemoryException ,会产生异常。When data structures or data sets that reside in memory become so large that the common language runtime is unable to allocate enough contiguous memory for them, an OutOfMemoryException exception results.

若要防止OutOfMemoryException这些异常,必须修改应用程序,以便减少内存中驻留的数据,或将数据分成需要较小的内存分配的段。To prevent the OutOfMemoryException exceptions, you must modify your application so that less data is resident in memory, or the data is divided into segments that require smaller memory allocations. 例如:For example:

  • 如果要从数据库中检索所有数据,然后在应用程序中对其进行筛选,以最大程度地减少到服务器的往返,则应修改查询以仅返回应用程序所需的数据的子集。If you are retrieving all of the data from a database and then filtering it in your app to minimize trips to the server, you should modify your queries to return only the subset of data that your app needs. 处理大型表时,多个查询几乎始终比检索单个表中的所有数据,然后对其进行操作的效率更高。When working with large tables, multiple queries are almost always more efficient than retrieving all of the data in a single table and then manipulating it.

  • 如果执行的是用户动态创建的查询,则应确保查询返回的记录数受到限制。If you are executing queries that users create dynamically, you should ensure that the number of records returned by the query is limited.

  • 如果你使用的大型数组或其他集合对象的大小会导致OutOfMemoryException异常,则应该将应用程序修改为使用子集来处理数据,而不是一次处理所有数据。If you are using large arrays or other collection objects whose size results in an OutOfMemoryException exception, you should modify your application to work the data in subsets rather than to work with it all at once.

下面的示例获取一个包含200000000浮点值的数组,然后计算其平均值。The following example gets a array that consists of 200 million floating-point values and then calculates their mean. 该示例的输出显示,因为该示例在计算平均值之前将整个数组存储在内存中, OutOfMemoryException因此将引发。The output from the example shows that, because the example stores the entire array in memory before it calculates the mean, an OutOfMemoryException is thrown.

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.
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.",
                              ctr)
         End If
      Next
      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
      Next
      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,并将计算所得的平均值和事例数返回到调用例程。The following example eliminates the OutOfMemoryException exception by processing the incoming data without storing the entire data set in memory, serializing the data to a file if necessary to permit further processing (these lines are commented out in the example, since in this case they produce a file whose size is greater than 1GB), and returning the calculated mean and the number of cases to the calling routine.

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;
            n++;
            // 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
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)
         Next
      Next
'       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

你要反复串联大型字符串。You are repeatedly concatenating large strings.

因为字符串是不可变的,所以每个字符串串联操作都会创建一个新字符串。Because strings are immutable, each string concatenation operation creates a new string. 对于小字符串或少量串联操作的影响,可忽略不计。The impact for small strings, or for a small number of concatenation operations, is negligible. 但对于大型字符串或大量串联操作,字符串连接可能会导致大量的内存分配和内存碎片,并导致性能不佳,还可能OutOfMemoryException出现异常。But for large strings or a very large number of concatenation operations, string concatenation can lead to a large number of memory allocations and memory fragmentation, poor performance, and possibly OutOfMemoryException exceptions.

在连接大型字符串或执行大量串联操作时,应使用StringBuilder类,而不是String类。When concatenating large strings or performing a large number of concatenation operations, you should use the StringBuilder class instead of the String class. 完成操作字符串后,通过StringBuilder StringBuilder.ToString调用方法将实例转换为字符串。When you have finished manipulating the string, convert the StringBuilder instance to a string by calling the StringBuilder.ToString method.

将大量对象固定在内存中。You pin a large number of objects in memory.

长时间将大量对象固定在内存中可能会使垃圾回收器难以分配连续的内存块。Pinning a large number of objects in memory for long periods can make it difficult for the garbage collector to allocate contiguous blocks of memory. 如果已将大量对象固定在内存中(例如,通过fixed使用中C#的语句GCHandle.Alloc(Object, GCHandleType)或通过使用的句柄类型GCHandleType.Pinned调用方法),则可以执行以下操作来解决OutOfMemoryException异常。If you've pinned a large number of objects in memory, for example by using the fixed statement in C# or by calling the GCHandle.Alloc(Object, GCHandleType) method with a handle type of GCHandleType.Pinned, you can do the following to address the OutOfMemoryException exception.

  • 评估是否确实需要固定每个对象,Evaluate whether each object really needs to be pinned,

  • 确保每个对象尽快取消固定。Ensure that each object is unpinned as soon as possible.

  • 确保每次调用GCHandle.Alloc(Object, GCHandleType)方法以固定内存时都有相应的GCHandle.Free方法调用方法来取消固定该内存。Make sure that each call to the GCHandle.Alloc(Object, GCHandleType) method to pin memory has a corresponding call to the GCHandle.Free method to unpin that memory.

以下 Microsoft 中间(MSIL)指令引发了OutOfMemoryException异常:The following Microsoft intermediate (MSIL) instructions throw an OutOfMemoryException exception:

构造函数

OutOfMemoryException()

初始化 OutOfMemoryException 类的新实例。Initializes a new instance of the OutOfMemoryException class.

OutOfMemoryException(SerializationInfo, StreamingContext)

用序列化数据初始化 OutOfMemoryException 类的新实例。Initializes a new instance of the OutOfMemoryException class with serialized data.

OutOfMemoryException(String)

用指定的错误消息初始化 OutOfMemoryException 类的新实例。Initializes a new instance of the OutOfMemoryException class with a specified error message.

OutOfMemoryException(String, Exception)

使用指定的错误消息和对作为此异常原因的内部异常的引用来初始化 OutOfMemoryException 类的新实例。Initializes a new instance of the OutOfMemoryException class with a specified error message and a reference to the inner exception that is the cause of this exception.

属性

Data

获取提供有关异常的其他用户定义信息的键/值对集合。Gets a collection of key/value pairs that provide additional user-defined information about the exception.

(继承自 Exception)
HelpLink

获取或设置指向与此异常关联的帮助文件链接。Gets or sets a link to the help file associated with this exception.

(继承自 Exception)
HResult

获取或设置 HRESULT(一个分配给特定异常的编码数字值)。Gets or sets HRESULT, a coded numerical value that is assigned to a specific exception.

(继承自 Exception)
InnerException

获取导致当前异常的 Exception 实例。Gets the Exception instance that caused the current exception.

(继承自 Exception)
Message

获取描述当前异常的消息。Gets a message that describes the current exception.

(继承自 Exception)
Source

获取或设置导致错误的应用程序或对象的名称。Gets or sets the name of the application or the object that causes the error.

(继承自 Exception)
StackTrace

获取调用堆栈上的即时框架字符串表示形式。Gets a string representation of the immediate frames on the call stack.

(继承自 Exception)
TargetSite

获取引发当前异常的方法。Gets the method that throws the current exception.

(继承自 Exception)

方法

Equals(Object)

确定指定的对象是否等于当前对象。Determines whether the specified object is equal to the current object.

(继承自 Object)
GetBaseException()

当在派生类中重写时,返回 Exception,它是一个或多个并发的异常的根源。When overridden in a derived class, returns the Exception that is the root cause of one or more subsequent exceptions.

(继承自 Exception)
GetHashCode()

用作默认哈希函数。Serves as the default hash function.

(继承自 Object)
GetObjectData(SerializationInfo, StreamingContext)

当在派生类中重写时,用关于异常的信息设置 SerializationInfoWhen overridden in a derived class, sets the SerializationInfo with information about the exception.

(继承自 Exception)
GetType()

获取当前实例的运行时类型。Gets the runtime type of the current instance.

(继承自 Exception)
MemberwiseClone()

创建当前 Object 的浅表副本。Creates a shallow copy of the current Object.

(继承自 Object)
ToString()

创建并返回当前异常的字符串表示形式。Creates and returns a string representation of the current exception.

(继承自 Exception)

事件

SerializeObjectState

当异常被序列化用来创建包含有关该异常的徐列出数据的异常状态对象时会出现该问题。Occurs when an exception is serialized to create an exception state object that contains serialized data about the exception.

(继承自 Exception)

适用于

另请参阅