OutOfMemoryException Třída

Definice

Výjimka, která je vyvolán, když není dostatek paměti pro pokračování v provádění 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
Dědičnost
OutOfMemoryException
Dědičnost
OutOfMemoryException
Odvozené
Atributy

Poznámky

OutOfMemoryException používá hodnotu HRESULT COR_E_OUTOFMEMORY, která má hodnotu 0x8007000E.

Seznam počátečních hodnot vlastností pro instanci nástroje najdete v OutOfMemoryException konstruktorechOutOfMemoryException.

Poznámka

Hodnota zděděné Data vlastnosti je vždy null.

Výjimka OutOfMemoryException má dvě hlavní příčiny:

  • Pokoušíte se rozšířit StringBuilder objekt za délku definovanou jeho StringBuilder.MaxCapacity vlastností.

  • Modul CLR (Common Language Runtime) nemůže přidělit dostatek souvislé paměti k úspěšnému provedení operace. Tuto výjimku může vyvolat jakékoli přiřazení vlastnosti nebo volání metody, které vyžaduje přidělení paměti. Další informace o příčině OutOfMemoryException výjimky najdete v blogovém příspěvku "Nedostatek paměti" Neodkazuje na fyzickou paměť.

    Tento typ OutOfMemoryException výjimky představuje katastrofické selhání. Pokud se rozhodnete výjimku zpracovat, měli byste zahrnout catch blok, který volá metodu Environment.FailFast ukončení aplikace a přidá položku do protokolu systémových událostí, jak je tomu v následujícím příkladu.

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

Mezi podmínky, za kterých se výjimka vyvolá, a akce, které můžete provést k jejímu odstranění, patří:

Voláte metodu StringBuilder.Insert .

Pokoušíte se zvětšit délku objektu StringBuilder nad velikost určenou jeho StringBuilder.MaxCapacity vlastností. Následující příklad znázorňuje OutOfMemoryException výjimku vyvolanou voláním StringBuilder.Insert(Int32, String, Int32) metody, když se příklad pokusí vložit řetězec, který by způsobil, že vlastnost objektu Length překročí maximální kapacitu.

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.

Pokud chcete chybu vyřešit, můžete udělat jednu z následujících možností:

Vaše aplikace běží jako 32bitový proces.

32bitové procesy můžou přidělit maximálně 2 GB paměti virtuálního uživatelského režimu ve 32bitových systémech a 4 GB paměti virtuálního uživatelského režimu v 64bitových systémech. To může modulu ClR (Common Language Runtime) ztížit přidělení dostatečné souvislé paměti v případě, že je potřeba velké přidělení. Naproti tomu 64bitové procesy mohou přidělit až 8 TB virtuální paměti. Pokud chcete tuto výjimku vyřešit, překompilujte aplikaci tak, aby cílila na 64bitovou platformu. Informace o cílení na konkrétní platformy v sadě Visual Studio najdete v tématu Postupy: Konfigurace projektů na cílové platformy.

Vaše aplikace uniká nespravovanými prostředky

Přestože je systém uvolňování paměti schopen uvolnit paměť přidělenou spravovaným typům, nespravuje paměť přidělenou nespravovaným prostředkům, jako jsou popisovače operačního systému (včetně popisovačů souborů, souborů mapovaných na paměť, kanálů, klíčů registru a popisovačů čekání) a bloků paměti přidělených přímo voláním rozhraní API systému Windows nebo voláním funkcí přidělování paměti, jako mallocje . Typy, které využívají nespravované prostředky, implementují IDisposable rozhraní.

Pokud používáte typ, který používá nespravované prostředky, měli byste po dokončení jeho použití volat jeho IDisposable.Dispose metodu. (Některé typy také implementují metodu Close , která je ve funkci shodná s metodou Dispose .) Další informace najdete v tématu Použití objektů, které implementují IDisposable .

Pokud jste vytvořili typ, který používá nespravované prostředky, ujistěte se, že jste implementovali model Dispose a v případě potřeby zadali finalizátor. Další informace najdete v tématech Implementace metody Dispose a Object.Finalize.

Pokoušíte se vytvořit velké pole v 64bitovém procesu.

Ve výchozím nastavení common language runtime v rozhraní .NET Framework nepovoluje jednotlivé objekty, jejichž velikost přesahuje 2 GB. Chcete-li přepsat toto výchozí nastavení, můžete použít nastavení konfiguračního <souboru gcAllowVeryLargeObjects> a povolit pole, jejichž celková velikost přesahuje 2 GB. V .NET Core je ve výchozím nastavení povolená podpora polí větších než 2 GB.

Pracujete s velmi velkými sadami dat (jako jsou pole, kolekce nebo databázové datové sady) v paměti.

Když datové struktury nebo datové sady, které se nacházejí v paměti, budou tak velké, že modul CLR (Common Language Runtime) pro ně nemůže přidělit dostatek souvislé paměti, dojde k výjimce OutOfMemoryException .

Pokud chcete těmto výjimkám OutOfMemoryException zabránit, musíte aplikaci upravit tak, aby v paměti bylo méně dat, nebo aby byla data rozdělena do segmentů, které vyžadují menší přidělení paměti. Příklad:

  • Pokud načítáte všechna data z databáze a pak je v aplikaci filtrujete, abyste minimalizovali cesty na server, měli byste upravit dotazy tak, aby vracely jenom podmnožinu dat, která vaše aplikace potřebuje. Při práci s velkými tabulkami je více dotazů téměř vždy efektivnější než načtení všech dat v jedné tabulce a následná manipulace s nimi.

  • Pokud provádíte dotazy, které uživatelé vytvářejí dynamicky, měli byste zajistit, aby byl počet záznamů vrácených dotazem omezený.

  • Pokud používáte velká pole nebo jiné objekty kolekce, jejichž velikost vede k výjimce OutOfMemoryException , měli byste aplikaci upravit tak, aby pracovala s daty v podmnožinách a nepracová s daty najednou.

Následující příklad získá matici, která se skládá z 200 milionů hodnot s plovoucí desetinnou čárkou, a pak vypočítá jejich střední hodnotu. Výstup z příkladu ukazuje, že vzhledem k tomu, že příklad ukládá celé pole do paměti před tím, než vypočítá průměr, OutOfMemoryException je vyvolána hodnota .

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.

Následující příklad eliminuje OutOfMemoryException výjimku tím, že zpracuje příchozí data bez uložení celé datové sady do paměti, serializuje data do souboru, pokud je to nutné, aby bylo možné další zpracování (tyto řádky jsou v příkladu zakomentovány, protože v tomto případě vytvářejí soubor s velikostí větší než 1 GB), a vrátí vypočítanou střední hodnotu a počet případů do rutiny volání.

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

Opakovaně zřetězení velkých řetězců.

Vzhledem k tomu, že řetězce jsou neměnné, každá operace zřetězení řetězců vytvoří nový řetězec. Dopad na malé řetězce nebo malý počet operací zřetězení je zanedbatelný. U velkých řetězců nebo velkého počtu operací zřetězení řetězců však může zřetězení řetězců vést k velkému počtu přidělení paměti a fragmentaci paměti, nízkému výkonu a možná OutOfMemoryException i k výjimkám.

Při zřetězení velkých řetězců nebo provádění velkého počtu operací zřetězení byste měli místo třídy použít StringBuilder třídu String . Po dokončení manipulace s řetězcem převeďte StringBuilder instanci na řetězec voláním StringBuilder.ToString metody .

Do paměti připnete velký počet objektů.

Připnutí velkého počtu objektů v paměti po dlouhou dobu může ztížit uvolňování paměti přidělení souvislých bloků paměti. Pokud jste v paměti připnuli velký počet objektů, například pomocí fixed příkazu v jazyce C# nebo voláním GCHandle.Alloc(Object, GCHandleType) metody s typem GCHandleType.Pinnedpopisovače , můžete výjimku vyřešit OutOfMemoryException následujícím způsobem.

  • Vyhodnoťte, jestli je opravdu potřeba připnout každý objekt.

  • Ujistěte se, že každý objekt je co nejdříve odepnutý.

  • Ujistěte se, že každé volání GCHandle.Alloc(Object, GCHandleType) metody pro připnutí paměti má odpovídající volání GCHandle.Free metody pro odepnutí této paměti.

Následující pokyny microsoft intermediate (MSIL) vyvolají OutOfMemoryException výjimku:

Konstruktory

OutOfMemoryException()

Inicializuje novou instanci OutOfMemoryException třídy.

OutOfMemoryException(SerializationInfo, StreamingContext)
Zastaralé.

Inicializuje novou instanci třídy OutOfMemoryException se serializovanými daty.

OutOfMemoryException(String)

Inicializuje novou instanci OutOfMemoryException třídy se zadanou chybovou zprávou.

OutOfMemoryException(String, Exception)

Inicializuje novou instanci OutOfMemoryException třídy se zadanou chybovou zprávou a odkazem na vnitřní výjimku, která je příčinou této výjimky.

Vlastnosti

Data

Získá kolekci párů klíč/hodnota, které poskytují další uživatelem definované informace o výjimce.

(Zděděno od Exception)
HelpLink

Získá nebo nastaví odkaz na soubor nápovědy přidružené k této výjimce.

(Zděděno od Exception)
HResult

Získá nebo nastaví HRESULT, kódovanou číselnou hodnotu, která je přiřazena ke konkrétní výjimce.

(Zděděno od Exception)
InnerException

Exception Získá instanci, která způsobila aktuální výjimku.

(Zděděno od Exception)
Message

Získá zprávu, která popisuje aktuální výjimku.

(Zděděno od Exception)
Source

Získá nebo nastaví název aplikace nebo objektu, který způsobuje chybu.

(Zděděno od Exception)
StackTrace

Získá řetězcovou reprezentaci okamžitých rámců v zásobníku volání.

(Zděděno od Exception)
TargetSite

Získá metodu, která vyvolá aktuální výjimku.

(Zděděno od Exception)

Metody

Equals(Object)

Určí, zda se zadaný objekt rovná aktuálnímu objektu.

(Zděděno od Object)
GetBaseException()

Při přepsání v odvozené třídě vrátí Exception hodnotu, která je původní příčinou jedné nebo více následných výjimek.

(Zděděno od Exception)
GetHashCode()

Slouží jako výchozí hashovací funkce.

(Zděděno od Object)
GetObjectData(SerializationInfo, StreamingContext)
Zastaralé.

Při přepsání v odvozené třídě nastaví SerializationInfo s informacemi o výjimce.

(Zděděno od Exception)
GetType()

Získá typ modulu runtime aktuální instance.

(Zděděno od Exception)
MemberwiseClone()

Vytvoří mělkou kopii aktuálního Objectsouboru .

(Zděděno od Object)
ToString()

Vytvoří a vrátí řetězcovou reprezentaci aktuální výjimky.

(Zděděno od Exception)

Událost

SerializeObjectState
Zastaralé.

Nastane, když je výjimka serializována k vytvoření objektu stavu výjimky, který obsahuje serializovaná data o výjimce.

(Zděděno od Exception)

Platí pro

Viz také