OutOfMemoryException Osztály

Definíció

A kivétel, amely akkor merül fel, ha nincs elegendő memória a program végrehajtásának folytatásához.

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
Öröklődés
OutOfMemoryException
Öröklődés
OutOfMemoryException
Származtatott
Attribútumok

Megjegyzések

OutOfMemoryException A HRESULT COR_E_OUTOFMEMORYfüggvényt használja, amelynek értéke 0x8007000E.

A OutOfMemoryException példány kezdeti tulajdonságainak listájáért tekintse meg a OutOfMemoryException konstruktorokat.

Note

Az örökölt Data tulajdonság értéke mindig null.

A OutOfMemoryException kivételnek két fő oka van:

  • Megpróbál kibontani egy objektumot StringBuilder a tulajdonsága által StringBuilder.MaxCapacity meghatározott hosszon túl.

  • A közös nyelvi futtatókörnyezet nem tud elegendő összefüggő memóriát lefoglalni egy művelet sikeres végrehajtásához. Ezt a kivételt bármely olyan tulajdonság-hozzárendelés vagy metódushívás okozhatja, amely memóriafoglalást igényel. A kivétel okával OutOfMemoryException kapcsolatos további információkért tekintse meg a "Memóriakihasználtság" című blogbejegyzést, amely nem hivatkozik a fizikai memóriára.

    Ez a OutOfMemoryException kivételtípus katasztrofális hibát jelez. Ha úgy dönt, hogy kezeli a kivételt, olyan blokkot catch kell tartalmaznia, amely meghívja a metódust az Environment.FailFast alkalmazás leállítására, és adjon hozzá egy bejegyzést a rendszer eseménynaplójához, ahogy az alábbi példa is teszi.

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

Néhány feltétel, amely mellett a kivételt ki lehet dobni, és a kiküszöbölése érdekében végrehajtható műveletek közé tartoznak a következők:

A metódust StringBuilder.Insert hívja meg.

Megkísérli növelni egy objektum hosszát StringBuilder a tulajdonsága által StringBuilder.MaxCapacity megadott méreten túl. Az alábbi példa a OutOfMemoryException metódus hívása StringBuilder.Insert(Int32, String, Int32) által okozott kivételt mutatja be, amikor a példa olyan sztringet próbál beszúrni, amely miatt az objektum tulajdonsága Length meghaladja a maximális kapacitást.

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.

A hiba elhárításához tegye az alábbiak egyikét:

Az alkalmazás 32 bites folyamatként fut.

A 32 bites folyamatok legfeljebb 2 GB virtuális felhasználói módú memóriát foglalhatnak le 32 bites rendszereken, és 4 GB virtuális felhasználói módú memóriát 64 bites rendszereken. Ez megnehezítheti, hogy a közös nyelvi futtatókörnyezet elegendő összefüggő memóriát foglaljon le, ha nagy foglalásra van szükség. Ezzel szemben a 64 bites folyamatok akár 8 TB virtuális memóriát is lefoglalhatnak. A kivétel megoldásához újrafordítással célozhat meg egy 64 bites platformot. Az egyes platformok Visual Studio való megcélzásával kapcsolatos információkért lásd: Beállítás: Projektek konfigurálása célplatformokra.

Az alkalmazás nem felügyelt erőforrásokat szivárogtat ki

Bár a szemétgyűjtő képes felszabadítani a felügyelt típusok számára lefoglalt memóriát, nem kezeli a nem felügyelt erőforrásokhoz, például az operációsrendszer-leírókhoz (beleértve a fájlokhoz tartozó leírókat, a memórialeképezett fájlokat, a csöveket, a beállításkulcsokat és a várakozási fogópontokat) és a közvetlenül Windows API-hívások vagy a memórialefoglalási függvények, például malloc által lefoglalt memóriablokkokat. A nem felügyelt erőforrásokat használó típusok implementálják a IDisposable felületet.

Ha nem felügyelt erőforrásokat használó típust használ, mindenképpen hívja meg a metódust IDisposable.Dispose , amikor befejezte a használatát. (Egyes típusok egy Close metódussal azonos metódust Dispose is implementálnak.) További információt az IDisposable-t implementáló objektumok használata című témakörben talál.

Ha olyan típust hozott létre, amely nem felügyelt erőforrásokat használ, győződjön meg arról, hogy implementálta az Elidegenítési mintát, és szükség esetén adott meg egy véglegesítőt. További információ: Implementing a Dispose metódus és Object.Finalize.

Nagy tömböt próbál létrehozni egy 64 bites folyamatban

Alapértelmezés szerint a .NET Framework közös nyelvi futtatókörnyezete nem engedélyezi a 2 GB-ot meghaladó méretű objektumok használatát. Az alapértelmezett beállítás felülbírálásához a <gcAllowVeryLargeObjects konfigurációs> fájlbeállításával engedélyezheti a 2 GB-nál nagyobb méretű tömböket. A .NET Core-on alapértelmezés szerint engedélyezve van a 2 GB-nál nagyobb tömbök támogatása.

Nagyon nagy adatkészletekkel (például tömbökkel, gyűjteményekkel vagy adatbázis-adatkészletekkel) dolgozik a memóriában.

Ha a memóriában található adatstruktúrák vagy adathalmazok olyan nagyok lesznek, hogy a közös nyelvi futtatókörnyezet nem tud elegendő összefüggő memóriát lefoglalni számukra, kivétel OutOfMemoryException jön létre.

A OutOfMemoryException kivételek elkerülése érdekében módosítania kell az alkalmazást, hogy kevesebb adat legyen a memóriában, vagy hogy az adatok olyan szegmensekre legyenek felosztva, amelyek kisebb memóriakiosztást igényelnek. Például:

  • Ha az összes adatot egy adatbázisból kéri le, majd szűri az alkalmazásban a kiszolgálóra való utazások minimalizálása érdekében, módosítsa a lekérdezéseket, hogy csak az alkalmazás által igényelt adathalmazt adja vissza. Nagy táblák használatakor több lekérdezés is majdnem mindig hatékonyabb, mint az összes adat beolvasása egyetlen táblában, majd annak manipulálása.

  • Ha dinamikusan létrehozott lekérdezéseket hajt végre, győződjön meg arról, hogy a lekérdezés által visszaadott rekordok száma korlátozott.

  • Ha nagy tömböket vagy más olyan gyűjteményobjektumokat használ, amelyek mérete kivételt OutOfMemoryException eredményez, az alkalmazást úgy kell módosítania, hogy az adatokat alhalmazokban dolgozza fel, nem pedig egyszerre.

Az alábbi példa egy 200 millió lebegőpontos értékből álló tömböt kap, majd kiszámítja a középértéküket. A példa kimenete azt mutatja, hogy mivel a példa a teljes tömböt a memóriában tárolja, mielőtt kiszámítja a középértéket, a rendszer eldob egy OutOfMemoryException értéket.

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.

Az alábbi példa kiküszöböli a OutOfMemoryException kivételt azáltal, hogy a bejövő adatokat úgy dolgozza fel, hogy nem tárolja a teljes adatkészletet a memóriában, és szükség esetén szerializálja az adatokat egy fájlba a további feldolgozás engedélyezéséhez (ezeket a sorokat a példában megjegyzésként fűzik hozzá, mivel ebben az esetben egy 1 GB-nál nagyobb méretű fájlt hoznak létre), és visszaadják a számított középértéket és az esetek számát a hívási rutinnak.

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

Ismétlődően összefűz nagy sztringeket.

Mivel a sztringek nem módosíthatók, minden sztringösszefűzési művelet új sztringet hoz létre. A kis sztringek vagy kis számú összefűzési művelet hatása elhanyagolható. Nagy sztringek vagy nagyon sok összefűzési művelet esetén azonban a sztringösszefűzés sok memóriafoglaláshoz és memóriatöredezettséghez, gyenge teljesítményhez és esetleg OutOfMemoryException kivételekhez vezethet.

Nagy sztringek összefűzésekor vagy nagy számú összefűzési művelet végrehajtásakor az StringBuilder osztályt kell használnia az String osztály helyett. Ha befejezte a sztring manipulálását, konvertálja a StringBuilder példányt sztringgé a StringBuilder.ToString metódus meghívásával.

Sok objektumot rögzíthet a memóriában.

Ha hosszú ideig sok objektumot rögzít a memóriában, az megnehezítheti a szemétgyűjtő számára az egyidejű memóriablokkok lefoglalását. Ha nagy számú objektumot rögzített a memóriában, például a fixed C# utasítással vagy a GCHandle.Alloc(Object, GCHandleType) metódus leírótípussal GCHandleType.Pinnedvaló meghívásával, a kivétel elhárításához OutOfMemoryException az alábbiakat teheti meg.

  • Annak kiértékelése, hogy az egyes objektumokat valóban rögzíteni kell-e,

  • Győződjön meg arról, hogy az egyes objektumok a lehető leghamarabb nem lesznek rögzítve.

  • Győződjön meg arról, hogy a GCHandle.Alloc(Object, GCHandleType) memória rögzítésére szolgáló metódus minden hívása rendelkezik a metódusnak megfelelő hívással a GCHandle.Free memória rögzítésének feloldásához.

Az alábbi Microsoft köztes (MSIL) utasítások OutOfMemoryException kivételt eredményeznek:

Konstruktorok

Name Description
OutOfMemoryException()

Inicializálja a OutOfMemoryException osztály új példányát.

OutOfMemoryException(SerializationInfo, StreamingContext)
Elavult.

Inicializálja az OutOfMemoryException osztály új példányát szerializált adatokkal.

OutOfMemoryException(String, Exception)

Inicializálja az OutOfMemoryException osztály új példányát egy megadott hibaüzenettel és a kivétel okaként szolgáló belső kivételre mutató hivatkozással.

OutOfMemoryException(String)

Inicializálja az OutOfMemoryException osztály új példányát egy megadott hibaüzenettel.

Tulajdonságok

Name Description
Data

Lekéri a kulcs-/érték párok gyűjteményét, amelyek további, felhasználó által definiált információkat biztosítanak a kivételről.

(Öröklődés forrása Exception)
HelpLink

Lekéri vagy beállítja a kivételhez társított súgófájlra mutató hivatkozást.

(Öröklődés forrása Exception)
HResult

Lekéri vagy beállítja a HRESULT-ot, egy kódolt numerikus értéket, amely egy adott kivételhez van hozzárendelve.

(Öröklődés forrása Exception)
InnerException

Lekéri az Exception aktuális kivételt okozó példányt.

(Öröklődés forrása Exception)
Message

Az aktuális kivételt leíró üzenet jelenik meg.

(Öröklődés forrása Exception)
Source

Lekéri vagy beállítja az alkalmazás vagy a hibát okozó objektum nevét.

(Öröklődés forrása Exception)
StackTrace

Lekéri a hívásverem közvetlen kereteinek sztringképét.

(Öröklődés forrása Exception)
TargetSite

Lekéri az aktuális kivételt okozó metódust.

(Öröklődés forrása Exception)

Metódusok

Name Description
Equals(Object)

Meghatározza, hogy a megadott objektum egyenlő-e az aktuális objektummal.

(Öröklődés forrása Object)
GetBaseException()

Ha egy származtatott osztály felül van bírálva, egy Exception vagy több későbbi kivétel kiváltó okát adja vissza.

(Öröklődés forrása Exception)
GetHashCode()

Ez az alapértelmezett kivonatoló függvény.

(Öröklődés forrása Object)
GetObjectData(SerializationInfo, StreamingContext)
Elavult.

Ha felül van bírálva egy származtatott osztályban, a SerializationInfo kivétel adatait adja meg.

(Öröklődés forrása Exception)
GetType()

Lekéri az aktuális példány futtatókörnyezeti típusát.

(Öröklődés forrása Exception)
MemberwiseClone()

Az aktuális Objectpéldány sekély másolatát hozza létre.

(Öröklődés forrása Object)
ToString()

Létrehozza és visszaadja az aktuális kivétel sztring-ábrázolását.

(Öröklődés forrása Exception)

esemény

Name Description
SerializeObjectState
Elavult.

Akkor fordul elő, ha a kivétel szerializálva van egy kivételállapot-objektum létrehozásához, amely szerializált adatokat tartalmaz a kivételről.

(Öröklődés forrása Exception)

A következőre érvényes:

Lásd még