Sdílet prostřednictvím


OutOfMemoryException Třída

Definice

Výjimka, která se vyvolá, 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 OutOfMemoryExceptionnaleznete v konstruktoru OutOfMemoryException.

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 nad rámec délky definované jeho StringBuilder.MaxCapacity vlastností.

  • Modul CLR (Common Language Runtime) nemůže přidělit dostatek souvislé paměti pro úspěšné 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 naleznete v blogovém příspěvku "Nedostatek paměti" neodkazuje na fyzickou paměť.

    Tento typ OutOfMemoryException výjimky představuje závažné selhání. Pokud se rozhodnete výjimku zpracovat, měli byste zahrnout catch blok, který volá metodu Environment.FailFast pro ukončení aplikace a přidat položku do systémového protokolu událostí, jak je znázorněno 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 je výjimka vyvoláná, a akce, které můžete provést k odstranění, zahrnují následující:

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čila jeho 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 provést některou z následujících akcí:

Aplikace běží jako 32bitový proces.

32bitové procesy mohou přidělit maximálně 2 GB paměti virtuálního uživatelského režimu v 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 ztížit přidělení dostatečné souvislé paměti v případě potřeby velkého přidělení modulu CLR (Common Language Runtime). Naproti tomu 64bitové procesy můžou 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 nespravované prostředky nespravuje

Přestože systém uvolňování paměti dokáže 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 do paměti, 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ělení paměti, jako mallocjsou . Typy, které využívají nespravované prostředky, implementují IDisposable rozhraní.

Pokud používáte typ, který používá nespravované prostředky, měli byste při jeho použití volat jeho IDisposable.Dispose metodu. (Některé typy také implementují metodu Close , která je stejná ve funkci jako Dispose metoda.) Další informace naleznete v tématu Použití objektů, které implementují IDisposable téma.

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

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

Modul CLR (Common Language Runtime) v rozhraní .NET Framework ve výchozím nastavení neumožňuje jednotlivé objekty, jejichž velikost přesahuje 2 GB. Pokud chcete toto výchozí nastavení přepsat, 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ž se datové struktury nebo datové sady umístěné v paměti stanou tak velkými, že modul CLR (Common Language Runtime) nemůže přidělit pro ně dostatečnou souvislou paměť, dojde k výjimce OutOfMemoryException .

Chcete-li zabránit OutOfMemoryException výjimkám, je nutné upravit aplikaci tak, aby méně dat bylo v paměti, nebo jsou data rozdělena do segmentů, které vyžadují menší přidělení paměti. Například:

  • Pokud načítáte všechna data z databáze a pak je filtrujete v aplikaci, 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čítání všech dat v jedné tabulce a následné manipulaci 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 fungovala data v podmnožinách, a ne pracovat s ní 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 protože příklad ukládá celé pole do paměti před tím, než vypočítá střední hodnotu, OutOfMemoryException je vyvolána.

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 zpracováním příchozích dat bez uložení celé sady dat do paměti, serializace dat do souboru v případě potřeby k povolení dalšího zpracování (tyto řádky jsou v příkladu okomentovány, protože v tomto případě vytvoří soubor, jehož velikost je větší než 1 GB) a vrátí počítanou střední hodnotu a počet případů do volající rutiny.

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 velmi velkého počtu operací zřetězení však může zřetězení řetězců vést k velkému počtu přidělení paměti a fragmentace paměti, nízkému výkonu a pravděpodobně OutOfMemoryException i 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.

Připnete velký počet objektů v paměti.

Připnutí velkého počtu objektů v paměti po dlouhou dobu může znesnadnit uvolňování paměti přidělení souvislých bloků paměti. Pokud jste připnuli velký počet objektů v paměti, 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 tuto výjimku vyřešit OutOfMemoryException následujícím způsobem.

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

  • Zajistěte, aby se každý objekt co nejdříve odepnul.

  • Ujistěte se, že každé volání GCHandle.Alloc(Object, GCHandleType) metody 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) vyvolá OutOfMemoryException výjimku:

Konstruktory

Name Description
OutOfMemoryException()

Inicializuje novou instanci OutOfMemoryException třídy.

OutOfMemoryException(SerializationInfo, StreamingContext)
Zastaralé.

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

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.

OutOfMemoryException(String)

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

Vlastnosti

Name Description
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ězcové znázornění 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

Name Description
Equals(Object)

Určuje, zda je zadaný objekt roven aktuálnímu objektu.

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

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

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

Slouží jako výchozí funkce hash.

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

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

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

(Zděděno od Exception)

Událost

Name Description
SerializeObjectState
Zastaralé.

Nastane, když je výjimka serializována vytvořit objekt stavu výjimky, který obsahuje serializovaná data o výjimce.

(Zděděno od Exception)

Platí pro

Viz také