Udostępnij za pośrednictwem


OutOfMemoryException Klasa

Definicja

Wyjątek zgłaszany, gdy za mało pamięci, aby kontynuować wykonywanie programu.

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
Dziedziczenie
OutOfMemoryException
Dziedziczenie
OutOfMemoryException
Pochodne
Atrybuty

Uwagi

OutOfMemoryException używa wartości HRESULT COR_E_OUTOFMEMORY, która ma wartość 0x8007000E.

Aby uzyskać listę początkowych wartości właściwości dla wystąpienia programu OutOfMemoryException, zobacz OutOfMemoryException konstruktory.

Uwaga

Wartość odziedziczonej Data właściwości to zawsze null.

Wyjątek OutOfMemoryException ma dwie główne przyczyny:

  • Próbujesz rozwinąć obiekt poza długością zdefiniowaną StringBuilder przez jego StringBuilder.MaxCapacity właściwość.

  • Środowisko uruchomieniowe języka wspólnego nie może przydzielić wystarczającej ilości pamięci, aby pomyślnie wykonać operację. Ten wyjątek może zostać zgłoszony przez dowolne przypisanie właściwości lub wywołanie metody, które wymaga alokacji pamięci. Aby uzyskać więcej informacji na temat przyczyny wyjątku OutOfMemoryException , zobacz wpis w blogu "Brak pamięci" Nie dotyczy pamięci fizycznej.

    Ten typ wyjątku OutOfMemoryException reprezentuje katastrofalną awarię. Jeśli zdecydujesz się obsłużyć wyjątek, należy uwzględnić catch blok, który wywołuje Environment.FailFast metodę, aby zakończyć działanie aplikacji i dodać wpis do dziennika zdarzeń systemowych, jak w poniższym przykładzie.

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

Niektóre warunki, w których jest zgłaszany wyjątek, a akcje, które można podjąć, aby wyeliminować je, obejmują następujące elementy:

Wywołujesz metodę StringBuilder.Insert .

Próbujesz zwiększyć długość StringBuilder obiektu poza rozmiar określony przez jego StringBuilder.MaxCapacity właściwość. Poniższy przykład ilustruje OutOfMemoryException wyjątek zgłaszany przez wywołanie StringBuilder.Insert(Int32, String, Int32) metody, gdy w przykładzie próbuje wstawić ciąg, który spowoduje przekroczenie maksymalnej pojemności właściwości obiektu 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
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.

Możesz wykonać jedną z następujących czynności, aby rozwiązać problem:

Aplikacja jest uruchamiana jako proces 32-bitowy.

Procesy 32-bitowe mogą przydzielić maksymalnie 2 GB pamięci w trybie użytkownika wirtualnego w systemach 32-bitowych i 4 GB pamięci w trybie użytkownika wirtualnego w systemach 64-bitowych. Może to utrudnić środowisko uruchomieniowe języka wspólnego przydzielanie wystarczającej ilości pamięci, gdy potrzebna jest duża alokacja. Natomiast 64-bitowe procesy mogą przydzielić maksymalnie 8 TB pamięci wirtualnej. Aby rozwiązać ten wyjątek, ponownie skompiluj aplikację, aby kierować do platformy 64-bitowej. Aby uzyskać informacje na temat określania docelowych platform w programie Visual Studio, zobacz Instrukcje: konfigurowanie projektów na platformach docelowych.

Twoja aplikacja wycieka niezarządzanych zasobów

Mimo że moduł odśmiecanie pamięci jest w stanie zwolnić pamięć przydzieloną do typów zarządzanych, nie zarządza pamięcią przydzieloną do niezarządzanych zasobów, takich jak uchwyty systemu operacyjnego (w tym uchwyty do plików, zamapowane pliki pamięci, potoki, klucze rejestru i uchwyty oczekiwania) i bloki pamięci przydzielone bezpośrednio przez wywołania interfejsu API systemu Windows lub wywołania funkcji alokacji pamięci, takie jak malloc. Typy wykorzystujące niezarządzane zasoby implementują IDisposable interfejs.

Jeśli używasz typu korzystającego z niezarządzanych zasobów, po zakończeniu korzystania z niej należy wywołać jego IDisposable.Dispose metodę. (Niektóre typy implementują również metodę Close , która jest identyczna w funkcji z Dispose metodą). Aby uzyskać więcej informacji, zobacz temat Using Objects That Implement IDisposable (Używanie obiektów implementujących funkcję IDisposable ).

Jeśli utworzono typ, który używa niezarządzanych zasobów, upewnij się, że zaimplementowano wzorzec Dispose, a w razie potrzeby podano finalizator. Aby uzyskać więcej informacji, zobacz Implementowanie metody Dispose i Object.Finalize.

Próbujesz utworzyć dużą tablicę w procesie 64-bitowym

Domyślnie środowisko uruchomieniowe języka wspólnego w programie .NET Framework nie zezwala na pojedyncze obiekty, których rozmiar przekracza 2 GB. Aby zastąpić tę wartość domyślną, możesz użyć <ustawienia pliku konfiguracji gcAllowVeryLargeObjects> , aby włączyć tablice, których całkowity rozmiar przekracza 2 GB. Na platformie .NET Core obsługa tablic o rozmiarze większym niż 2 GB jest domyślnie włączona.

Pracujesz z bardzo dużymi zestawami danych (takimi jak tablice, kolekcje lub zestawy danych bazy danych) w pamięci.

Gdy struktury danych lub zestawy danych znajdujące się w pamięci stają się tak duże, że środowisko uruchomieniowe języka wspólnego nie może przydzielić wystarczającej ilości pamięci dla nich, OutOfMemoryException wynik wyjątku.

Aby zapobiec OutOfMemoryException wyjątkom, należy zmodyfikować aplikację tak, aby mniej danych było w pamięci lub dane są podzielone na segmenty, które wymagają mniejszych alokacji pamięci. Na przykład:

  • Jeśli pobierasz wszystkie dane z bazy danych, a następnie filtrujesz je w aplikacji, aby zminimalizować podróże do serwera, należy zmodyfikować zapytania, aby zwrócić tylko podzbiór danych, których potrzebuje aplikacja. Podczas pracy z dużymi tabelami wiele zapytań jest prawie zawsze bardziej wydajnych niż pobieranie wszystkich danych w jednej tabeli, a następnie manipulowanie nimi.

  • Jeśli wykonujesz zapytania tworzone dynamicznie przez użytkowników, upewnij się, że liczba rekordów zwracanych przez zapytanie jest ograniczona.

  • Jeśli używasz dużych tablic lub innych obiektów kolekcji, których rozmiar powoduje OutOfMemoryException wyjątek, należy zmodyfikować aplikację, aby pracować z danymi w podzestawach, a nie pracować z tym wszystkim jednocześnie.

Poniższy przykład pobiera tablicę składającą się z 200 milionów wartości zmiennoprzecinkowych, a następnie oblicza średnią. Dane wyjściowe z przykładu pokazują, że ponieważ przykład przechowuje całą tablicę w pamięci, zanim obliczy średnią, OutOfMemoryException zostanie zgłoszony.

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.

Poniższy przykład eliminuje OutOfMemoryException wyjątek przez przetwarzanie danych przychodzących bez przechowywania całego zestawu danych w pamięci, serializowanie danych do pliku w razie potrzeby w celu zezwolenia na dalsze przetwarzanie (te wiersze są komentowane w tym przykładzie, ponieważ w tym przypadku tworzą plik, którego rozmiar jest większy niż 1 GB) i zwracają średnią obliczeniową i liczbę przypadków do procedury wywołującej.

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

Wielokrotnie łączysz duże ciągi.

Ponieważ ciągi są niezmienne, każda operacja łączenia ciągów tworzy nowy ciąg. Wpływ małych ciągów lub małej liczby operacji łączenia jest nieznaczny. Jednak w przypadku dużych ciągów lub bardzo dużej liczby operacji łączenia łączenie ciągów może prowadzić do dużej liczby alokacji pamięci i fragmentacji pamięci, niskiej wydajności i ewentualnie OutOfMemoryException wyjątków.

Podczas łączenia dużych ciągów lub wykonywania dużej liczby operacji łączenia należy użyć StringBuilder klasy zamiast String klasy . Po zakończeniu manipulowania ciągiem przekonwertuj StringBuilder wystąpienie na ciąg, wywołując metodę StringBuilder.ToString .

Przypinasz dużą liczbę obiektów w pamięci.

Przypinanie dużej liczby obiektów w pamięci przez długi czas może utrudnić moduł odśmiecania pamięci w celu przydzielenia ciągłych bloków pamięci. Jeśli przypięliśmy dużą liczbę obiektów w pamięci, na przykład za pomocą fixed instrukcji w języku C# lub wywołując GCHandle.Alloc(Object, GCHandleType) metodę o typie uchwytu GCHandleType.Pinned, możesz wykonać następujące czynności, aby rozwiązać OutOfMemoryException ten wyjątek.

  • Oceń, czy każdy obiekt naprawdę musi być przypięty,

  • Upewnij się, że każdy obiekt jest odpiętywany tak szybko, jak to możliwe.

  • Upewnij się, że każde wywołanie GCHandle.Alloc(Object, GCHandleType) metody przypinania pamięci ma odpowiednie wywołanie metody , GCHandle.Free aby odpiąć tę pamięć.

Następujące instrukcje dotyczące platformy Microsoft Intermediate (MSIL) zgłaszają OutOfMemoryException wyjątek:

Konstruktory

OutOfMemoryException()

Inicjuje nowe wystąpienie klasy OutOfMemoryException.

OutOfMemoryException(SerializationInfo, StreamingContext)
Przestarzałe.

Inicjuje nowe wystąpienie klasy OutOfMemoryException z zserializowanymi danymi.

OutOfMemoryException(String)

Inicjuje OutOfMemoryException nowe wystąpienie klasy z określonym komunikatem o błędzie.

OutOfMemoryException(String, Exception)

Inicjuje nowe wystąpienie OutOfMemoryException klasy z określonym komunikatem o błędzie i odwołaniem do wewnętrznego wyjątku, który jest przyczyną tego wyjątku.

Właściwości

Data

Pobiera kolekcję par klucz/wartość, które zapewniają dodatkowe informacje zdefiniowane przez użytkownika dotyczące wyjątku.

(Odziedziczone po Exception)
HelpLink

Pobiera lub ustawia link do pliku pomocy skojarzonego z tym wyjątkiem.

(Odziedziczone po Exception)
HResult

Pobiera lub ustawia HRESULT, zakodowaną wartość liczbową przypisaną do określonego wyjątku.

(Odziedziczone po Exception)
InnerException

Exception Pobiera wystąpienie, które spowodowało bieżący wyjątek.

(Odziedziczone po Exception)
Message

Pobiera komunikat opisujący bieżący wyjątek.

(Odziedziczone po Exception)
Source

Pobiera lub ustawia nazwę aplikacji lub obiektu, który powoduje błąd.

(Odziedziczone po Exception)
StackTrace

Pobiera reprezentację ciągu natychmiastowych ramek w stosie wywołań.

(Odziedziczone po Exception)
TargetSite

Pobiera metodę, która zgłasza bieżący wyjątek.

(Odziedziczone po Exception)

Metody

Equals(Object)

Określa, czy dany obiekt jest taki sam, jak bieżący obiekt.

(Odziedziczone po Object)
GetBaseException()

W przypadku zastąpienia w klasie pochodnej zwraca Exception główną przyczynę co najmniej jednego kolejnego wyjątku.

(Odziedziczone po Exception)
GetHashCode()

Służy jako domyślna funkcja skrótu.

(Odziedziczone po Object)
GetObjectData(SerializationInfo, StreamingContext)
Przestarzałe.

Po przesłonięciu w klasie pochodnej ustawia SerializationInfo wartość z informacjami o wyjątku.

(Odziedziczone po Exception)
GetType()

Pobiera typ środowiska uruchomieniowego bieżącego wystąpienia.

(Odziedziczone po Exception)
MemberwiseClone()

Tworzy płytkią kopię bieżącego Objectelementu .

(Odziedziczone po Object)
ToString()

Tworzy i zwraca reprezentację ciągu bieżącego wyjątku.

(Odziedziczone po Exception)

Zdarzenia

SerializeObjectState
Przestarzałe.

Występuje, gdy wyjątek jest serializowany w celu utworzenia obiektu stanu wyjątku zawierającego serializowane dane o wyjątku.

(Odziedziczone po Exception)

Dotyczy

Zobacz też