OutOfMemoryException Sınıf

Tanım

Bir programın yürütülmesine devam etmek için yeterli bellek olmadığında oluşan özel durum.

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
Devralma
OutOfMemoryException
Devralma
OutOfMemoryException
Türetilmiş
Öznitelikler

Açıklamalar

OutOfMemoryException değeri 0x8007000E olan HRESULT COR_E_OUTOFMEMORYkullanır.

örneğinin ilk özellik değerlerinin OutOfMemoryExceptionlistesi için oluşturuculara OutOfMemoryException bakın.

Not

Devralınan Data özelliğin değeri her zaman nullşeklindedir.

Bir OutOfMemoryException özel durumun iki ana nedeni vardır:

  • Bir StringBuilder nesneyi özelliği tarafından StringBuilder.MaxCapacity tanımlanan uzunluktan daha fazla genişletmeye çalışıyorsunuz.

  • Ortak dil çalışma zamanı, bir işlemi başarıyla gerçekleştirmek için yeterli bitişik bellek ayıramaz. Bu özel durum, bellek ayırma gerektiren herhangi bir özellik ataması veya yöntem çağrısı tarafından oluşturulabilir. Özel durumun nedeni OutOfMemoryException hakkında daha fazla bilgi için "Yetersiz Bellek" Fiziksel Belleğe Başvurmuyor blog gönderisine bakın.

    Bu tür OutOfMemoryException bir özel durum, yıkıcı bir hatayı temsil eder. Özel durumu işlemeyi seçerseniz, aşağıdaki örnekte olduğu gibi uygulamanızı sonlandırmak ve sistem olay günlüğüne bir giriş eklemek için yöntemini çağıran Environment.FailFast bir blok eklemeniz catch gerekir.

    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
    
    try
        // Outer block to handle any unexpected exceptions.
        try
            let s = "This"
            let s = s.Insert(2, "is ")
    
            // Throw an OutOfMemoryException exception.
            raise (OutOfMemoryException())
        with
        | :? 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()
          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...
    

Özel durumun oluşturulduğu koşullardan bazıları ve bunu ortadan kaldırmak için gerçekleştirebileceğiniz eylemler şunlardır:

yöntemini çağırıyorsunuz StringBuilder.Insert .

Bir StringBuilder nesnenin uzunluğunu özelliği tarafından StringBuilder.MaxCapacity belirtilen boyutun ötesinde artırmaya çalışıyorsunuz. Aşağıdaki örnek, nesnenin Length özelliğinin OutOfMemoryException maksimum kapasitesini aşmasına StringBuilder.Insert(Int32, String, Int32) neden olacak bir dize eklemeye çalıştığında yöntemi çağrısı tarafından oluşan özel durumu gösterir.

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
try
    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 ")
      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.

Hatayı gidermek için aşağıdakilerden birini yapabilirsiniz:

Uygulamanız 32 bit işlem olarak çalışır.

32 bit işlemler, 32 bit sistemlerde en fazla 2 GB sanal kullanıcı modu belleği ve 64 bit sistemlerde 4 GB sanal kullanıcı modu belleği ayırabilir. Bu, büyük bir ayırma gerektiğinde ortak dil çalışma zamanının yeterli bitişik bellek ayırmasını zorlaştırabilir. Buna karşılık, 64 bit işlemler 8 TB'a kadar sanal bellek ayırabilir. Bu özel durumu gidermek için uygulamanızı 64 bitlik bir platformu hedef olacak şekilde yeniden derlenin. Visual Studio'da belirli platformları hedefleme hakkında bilgi için bkz . Nasıl yapılır: Projeleri Hedef Platformlara Yapılandırma.

Uygulamanız yönetilmeyen kaynakları sızdırıyor

Çöp toplayıcı yönetilen türlere ayrılan belleği boşaltabilse de, işletim sistemi tanıtıcıları (dosyalara yönelik tanıtıcılar, belleğe eşlenen dosyalar, kanallar, kayıt defteri anahtarları ve bekleme tanıtıcıları dahil) gibi yönetilmeyen kaynaklara ayrılan belleği ve doğrudan Windows API çağrıları veya gibi mallocbellek ayırma işlevlerine yapılan çağrılar tarafından ayrılan bellek bloklarını yönetmez. Yönetilmeyen kaynakları kullanan türler arabirimini IDisposable uygular.

Yönetilmeyen kaynakları kullanan bir tür kullanıyorsanız, kullanmayı bitirdiğinizde yöntemini çağırdığınızdan IDisposable.Dispose emin olmalısınız. (Bazı türler, işlevde bir Close yöntemle aynı olan bir Dispose yöntemi de uygular.) Daha fazla bilgi için IDisposable Uygulayan Nesneleri Kullanma konusuna bakın.

Yönetilmeyen kaynakları kullanan bir tür oluşturduysanız Dispose desenini uyguladığınıza ve gerekirse bir sonlandırıcı sağladığınıza emin olun. Daha fazla bilgi için bkz . Dispose yöntemini uygulama ve Object.Finalize.

64 bitlik bir işlemde büyük bir dizi oluşturmaya çalışıyorsunuz

Varsayılan olarak, .NET Framework'teki ortak dil çalışma zamanı boyutu 2 GB'ı aşan tek nesnelere izin vermez. Bu varsayılanı geçersiz kılmak için gcAllowVeryLargeObjects> yapılandırma dosyası ayarını kullanarak< toplam boyutu 2 GB'ı aşan dizileri etkinleştirebilirsiniz. .NET Core'da, 2 GB'tan büyük diziler için destek varsayılan olarak etkindir.

Bellekte çok büyük veri kümeleri (diziler, koleksiyonlar veya veritabanı veri kümeleri gibi) ile çalışıyorsunuz.

Bellekte bulunan veri yapıları veya veri kümeleri, ortak dil çalışma zamanının bunlar için yeterli bitişik bellek ayıramayacağı kadar büyük hale geldiğinde, bir OutOfMemoryException özel durum sonucu verir.

Özel durumları önlemek OutOfMemoryException için, uygulamanızı daha az verinin bellekte yer alması veya verilerin daha küçük bellek ayırmaları gerektiren segmentlere bölünmesi için değiştirmeniz gerekir. Örnek:

  • Bir veritabanından tüm verileri alıyor ve ardından sunucuya gidişleri en aza indirmek için uygulamanızda filtrelediyseniz, sorgularınızı yalnızca uygulamanızın ihtiyaç duyduğu veri alt kümesini döndürecek şekilde değiştirmeniz gerekir. Büyük tablolarla çalışırken, birden çok sorgu neredeyse her zaman tek bir tablodaki tüm verileri alıp düzenlemekten daha verimlidir.

  • Kullanıcıların dinamik olarak oluşturduğu sorguları yürütüyorsanız, sorgu tarafından döndürülen kayıt sayısının sınırlı olduğundan emin olmanız gerekir.

  • Boyutu özel durumla OutOfMemoryException sonuçlanan büyük diziler veya diğer koleksiyon nesneleri kullanıyorsanız, uygulamanızı tek seferde çalışmak yerine verileri alt kümelerde çalışacak şekilde değiştirmeniz gerekir.

Aşağıdaki örnek, 200 milyon kayan nokta değerinden oluşan bir dizi alır ve sonra bunların ortalamasını hesaplar. Örnekten elde ettiği çıkış, örneğin ortalamayı hesaplamadan önce dizinin tamamını bellekte depoladığından bir OutOfMemoryException oluşturulur.

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.",
                              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.

Aşağıdaki örnek, veri kümesinin tamamını bellekte depolamadan gelen verileri işleyerek, daha fazla işlemeye izin vermek için gerekirse verileri bir dosyaya seri hale getirerek (bu örnekte boyutu 1 GB'tan büyük bir dosya oluşturduğundan bu satırlar açıklama satırı yapılır) ve hesaplanan ortalamayı ve servis talebi sayısını çağırma yordamına döndürerek özel durumu ortadan kaldırır OutOfMemoryException .

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
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)
         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

Büyük dizeleri art arda birleştirirsiniz.

Dizeler sabit olduğundan, her dize birleştirme işlemi yeni bir dize oluşturur. Küçük dizelerin veya az sayıda birleştirme işleminin etkisi göz ardı edilebilir. Ancak büyük dizeler veya çok fazla sayıda birleştirme işlemi için dize birleştirme çok sayıda bellek ayırmasına ve bellek parçalanmasına, düşük performansa ve muhtemelen OutOfMemoryException özel durumlara yol açabilir.

Büyük dizeleri birleştirirken veya çok sayıda birleştirme işlemi gerçekleştirirken, sınıfı yerine sınıfını String kullanmanız StringBuilder gerekir. Dizeyi düzenlemeyi bitirdiğinizde, yöntemini çağırarak örneği bir dizeye dönüştürün StringBuilderStringBuilder.ToString .

Belleğe çok sayıda nesne sabitlersiniz.

Bellekte uzun süreler boyunca çok sayıda nesne sabitlemek, atık toplayıcının bitişik bellek bloklarını ayırmasını zorlaştırabilir. Belleğe çok sayıda nesne sabitlediyseniz, örneğin C# dilinde deyimini fixed kullanarak veya yöntemini tanıtıcı türüyle GCHandleType.Pinnedçağırarak GCHandle.Alloc(Object, GCHandleType) özel durumu ele OutOfMemoryException almak için aşağıdakileri yapabilirsiniz.

  • Her nesnenin gerçekten sabitlenmesi gerekip gerekmediğini değerlendirin,

  • Her nesnenin mümkün olan en kısa sürede kaldırıldığından emin olun.

  • Belleği sabitlemek için yöntemine yapılan her çağrının GCHandle.Alloc(Object, GCHandleType) , bu belleği kaldırmak için yöntemine GCHandle.Free karşılık gelen bir çağrısı olduğundan emin olun.

Aşağıdaki Microsoft ara (MSIL) yönergeleri bir OutOfMemoryException özel durum oluşturur:

Oluşturucular

OutOfMemoryException()

OutOfMemoryException sınıfının yeni bir örneğini başlatır.

OutOfMemoryException(SerializationInfo, StreamingContext)
Geçersiz.

OutOfMemoryException sınıfının yeni bir örneğini serileştirilmiş verilerle başlatır.

OutOfMemoryException(String)

Belirtilen hata iletisiyle sınıfının yeni bir örneğini OutOfMemoryException başlatır.

OutOfMemoryException(String, Exception)

Belirtilen bir hata iletisi ve bu özel durumun nedeni olan iç özel duruma başvuru ile sınıfının yeni bir örneğini OutOfMemoryException başlatır.

Özellikler

Data

Özel durum hakkında kullanıcı tanımlı ek bilgiler sağlayan bir anahtar/değer çifti koleksiyonu alır.

(Devralındığı yer: Exception)
HelpLink

Bu özel durumla ilişkili yardım dosyasının bağlantısını alır veya ayarlar.

(Devralındığı yer: Exception)
HResult

Belirli bir özel duruma atanan kodlanmış sayısal bir değer olan HRESULT değerini alır veya ayarlar.

(Devralındığı yer: Exception)
InnerException

Geçerli özel duruma Exception neden olan örneği alır.

(Devralındığı yer: Exception)
Message

Geçerli özel durumu açıklayan bir ileti alır.

(Devralındığı yer: Exception)
Source

Hataya neden olan uygulamanın veya nesnenin adını alır veya ayarlar.

(Devralındığı yer: Exception)
StackTrace

Çağrı yığınındaki anlık çerçevelerin dize gösterimini alır.

(Devralındığı yer: Exception)
TargetSite

Geçerli özel durumu oluşturan yöntemini alır.

(Devralındığı yer: Exception)

Yöntemler

Equals(Object)

Belirtilen nesnenin geçerli nesneye eşit olup olmadığını belirler.

(Devralındığı yer: Object)
GetBaseException()

Türetilmiş bir sınıfta geçersiz kılındığında, sonraki bir veya daha fazla özel durumun kök nedeni olan değerini döndürür Exception .

(Devralındığı yer: Exception)
GetHashCode()

Varsayılan karma işlevi işlevi görür.

(Devralındığı yer: Object)
GetObjectData(SerializationInfo, StreamingContext)
Geçersiz.

Türetilmiş bir sınıfta geçersiz kılındığında, özel durum hakkındaki bilgilerle öğesini ayarlar SerializationInfo .

(Devralındığı yer: Exception)
GetType()

Geçerli örneğin çalışma zamanı türünü alır.

(Devralındığı yer: Exception)
MemberwiseClone()

Geçerli Objectöğesinin sığ bir kopyasını oluşturur.

(Devralındığı yer: Object)
ToString()

Geçerli özel durumun dize gösterimini oluşturur ve döndürür.

(Devralındığı yer: Exception)

Ekinlikler

SerializeObjectState
Geçersiz.

Bir özel durum, özel durum hakkında serileştirilmiş veriler içeren bir özel durum nesnesi oluşturmak üzere seri hale getirildiğinde gerçekleşir.

(Devralındığı yer: Exception)

Şunlara uygulanır

Ayrıca bkz.