OutOfMemoryException 類別

定義

當沒有足夠的記憶體繼續執行程式時,所擲回的例外狀況。The exception that is thrown when there is not enough memory to continue the execution of a program.

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
繼承
OutOfMemoryException
繼承
OutOfMemoryException
衍生
屬性

備註

OutOfMemoryException 使用 HRESULT COR_E_OUTOFMEMORY ,其值為0x8007000E。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 一律為 nullThe value of the inherited Data property is always null.

OutOfMemoryException例外狀況有兩個主要原因:An OutOfMemoryException exception has two major causes:

  • 您嘗試展開的 StringBuilder 物件超過其屬性定義的長度 StringBuilder.MaxCapacityYou are attempting to expand a StringBuilder object beyond the length defined by its StringBuilder.MaxCapacity property.

  • Common language runtime 無法配置足夠的連續記憶體來成功執行操作。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 ,請參閱「記憶體不足」的 blog 文章 未參考實體記憶體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.MaxCapacityYou 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. 這可能會讓 common language runtime 在需要大量配置時,更難以配置足夠的連續記憶體。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

雖然垃圾收集行程能夠釋出配置給 managed 型別的記憶體,但它並不會管理配置給非受控資源的記憶體,例如作業系統控制碼 (包括檔案的控制碼、記憶體對應檔、管道、登錄機碼,) 以及由 Windows API 呼叫直接配置的記憶體區塊,或呼叫記憶體配置函數(例如) mallocAlthough 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.

如果您已建立使用非受控資源的類型,請確定您已執行處置模式,並在必要時提供完成項。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 中的 common language runtime 不允許大小超過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.

當位於記憶體中的資料結構或資料集變成很大時,common language runtime 無法為它們配置足夠的連續記憶體,就會 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. 但是針對大型字串或非常大量的串連作業,字串串連可能會導致大量的記憶體配置和記憶體分散、效能不佳,以及可能的例外狀況 OutOfMemoryExceptionBut 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.ToStringWhen 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()

在衍生類別中覆寫時,傳回一或多個後續的例外狀況的根本原因 ExceptionWhen 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)

適用於

另請參閱