OutOfMemoryException Classe

Definizione

Eccezione generata quando non vi è memoria sufficiente per continuare l'esecuzione di un programma.

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
Ereditarietà
OutOfMemoryException
Ereditarietà
OutOfMemoryException
Derivato
Attributi

Commenti

OutOfMemoryException usa HRESULT COR_E_OUTOFMEMORY, che ha il valore 0x8007000E.

Per un elenco di valori di proprietà iniziali per un'istanza di OutOfMemoryException, vedere il OutOfMemoryException costruttori.

Nota

Il valore della proprietà ereditata Data è sempre null.

Un'eccezione OutOfMemoryException presenta due cause principali:

  • Si sta tentando di espandere un StringBuilder oggetto oltre la lunghezza definita dalla relativa StringBuilder.MaxCapacity proprietà.

  • Common Language Runtime non può allocare memoria contigua sufficiente per eseguire correttamente un'operazione. Questa eccezione può essere generata da qualsiasi assegnazione di proprietà o chiamata al metodo che richiede un'allocazione di memoria. Per altre informazioni sulla causa dell'eccezione OutOfMemoryException , vedere il post di blog "Memoria insufficiente" non fa riferimento alla memoria fisica.

    Questo tipo di OutOfMemoryException eccezione rappresenta un errore irreversibile. Se scegli di gestire l'eccezione, devi includere un catch blocco che chiama il metodo per terminare l'app Environment.FailFast e aggiungere una voce al registro eventi di sistema, come nell'esempio seguente.

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

Alcune delle condizioni in cui viene generata l'eccezione e le azioni che è possibile eseguire per eliminarla includono quanto segue:

Si sta chiamando il StringBuilder.Insert metodo .

Si sta tentando di aumentare la lunghezza di un StringBuilder oggetto oltre le dimensioni specificate dalla relativa StringBuilder.MaxCapacity proprietà. Nell'esempio seguente viene illustrata l'eccezione OutOfMemoryException generata da una chiamata al StringBuilder.Insert(Int32, String, Int32) metodo quando l'esempio tenta di inserire una stringa che provocherebbe il superamento della capacità massima della proprietà dell'oggetto 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.

Per risolvere l'errore, è possibile eseguire una delle operazioni seguenti:

L'app viene eseguita come processo a 32 bit.

I processi a 32 bit possono allocare un massimo di 2 GB di memoria in modalità utente virtuale nei sistemi a 32 bit e 4 GB di memoria in modalità utente virtuale nei sistemi a 64 bit. Ciò può rendere più difficile per Common Language Runtime allocare memoria contigua sufficiente quando è necessaria un'allocazione di grandi dimensioni. Al contrario, i processi a 64 bit possono allocare fino a 8 TB di memoria virtuale. Per risolvere questa eccezione, ricompilare l'app come destinazione di una piattaforma a 64 bit. Per informazioni sulla destinazione di piattaforme specifiche in Visual Studio, vedere Procedura: Configurare progetti per piattaforme di destinazione.

L'app perde risorse non gestite

Anche se il Garbage Collector è in grado di liberare memoria allocata ai tipi gestiti, non gestisce la memoria allocata a risorse non gestite, ad esempio handle del sistema operativo (inclusi handle per file, file mappati alla memoria, pipe, chiavi del Registro di sistema e handle di attesa) e blocchi di memoria allocati direttamente da chiamate API Windows o da chiamate a funzioni di allocazione di memoria, ad esempio malloc. I tipi che utilizzano risorse non gestite implementano l'interfaccia IDisposable .

Se si utilizza un tipo che usa risorse non gestite, è necessario chiamare il relativo IDisposable.Dispose metodo al termine dell'uso. Alcuni tipi implementano anche un Close metodo identico nella funzione a un Dispose metodo. Per altre informazioni, vedere l'argomento Using Objects that Implement IDisposable .

Se è stato creato un tipo che usa risorse non gestite, assicurarsi di aver implementato il modello Dispose e, se necessario, fornito un finalizzatore. Per altre informazioni, vedere Implementazione di un metodo Dispose e Object.Finalize.

Si sta tentando di creare una matrice di grandi dimensioni in un processo a 64 bit

Per impostazione predefinita, Common Language Runtime in .NET Framework non consente singoli oggetti le cui dimensioni superano i 2 GB. Per eseguire l'override di questo valore predefinito, è possibile usare l'impostazione del <gcAllowVeryLargeObjects> file di configurazione per abilitare le matrici le cui dimensioni totali superano 2 GB. In .NET Core il supporto per matrici di dimensioni superiori a 2 GB è abilitato per impostazione predefinita.

Si stiano usando set di dati di grandi dimensioni, ad esempio matrici, raccolte o set di dati di database, in memoria.

Quando le strutture di dati o i set di dati che risiedono in memoria diventano così grandi che Common Language Runtime non è in grado di allocare memoria contigua sufficiente, viene restituita un'eccezione OutOfMemoryException .

Per evitare le eccezioni, è necessario modificare l'applicazione OutOfMemoryException in modo che meno dati si trovino in memoria o che i dati siano divisi in segmenti che richiedono allocazioni di memoria più piccole. Ad esempio:

  • Se stai recuperando tutti i dati da un database e filtrandoli nell'app per ridurre al minimo i viaggi al server, devi modificare le query per restituire solo il subset di dati necessari per l'app. Quando si usano tabelle di grandi dimensioni, più query sono quasi sempre più efficienti rispetto al recupero di tutti i dati in una singola tabella e quindi alla modifica.

  • Se si eseguono query create dinamicamente dagli utenti, è necessario assicurarsi che il numero di record restituiti dalla query sia limitato.

  • Se si usano matrici di grandi dimensioni o altri oggetti di raccolta le cui dimensioni generano un'eccezione OutOfMemoryException , è necessario modificare l'applicazione in modo da utilizzare i dati in subset anziché usarli tutti contemporaneamente.

L'esempio seguente ottiene una matrice costituita da 200 milioni di valori a virgola mobile e quindi calcola la media. L'output dell'esempio mostra che, poiché l'esempio archivia l'intera matrice in memoria prima di calcolare la media, viene generata un'eccezione OutOfMemoryException .

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.

Nell'esempio seguente viene eliminata l'eccezione OutOfMemoryException elaborando i dati in ingresso senza archiviare l'intero set di dati in memoria, serializzando i dati in un file se necessario per consentire un'ulteriore elaborazione (queste righe vengono commentate nell'esempio, poiché in questo caso producono un file le cui dimensioni sono maggiori di 1 GB) e restituendo la media calcolata e il numero di case alla routine chiamante.

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

Si concatenano ripetutamente stringhe di grandi dimensioni.

Poiché le stringhe non sono modificabili, ogni operazione di concatenazione di stringhe crea una nuova stringa. L'impatto per stringhe di piccole dimensioni o per un numero ridotto di operazioni di concatenazione è trascurabile. Tuttavia, per stringhe di grandi dimensioni o un numero molto elevato di operazioni di concatenazione delle stringhe, la concatenazione di stringhe può causare un numero elevato di allocazioni di memoria e frammentazione della memoria, prestazioni scarse ed eventualmente OutOfMemoryException eccezioni.

Quando si concatenano stringhe di grandi dimensioni o si eseguono un numero elevato di operazioni di concatenazione, è consigliabile usare la StringBuilder classe anziché la String classe . Al termine della modifica della stringa, convertire l'istanza StringBuilder in una stringa chiamando il StringBuilder.ToString metodo .

È possibile aggiungere un numero elevato di oggetti in memoria.

L'aggiunta di un numero elevato di oggetti in memoria per lunghi periodi può rendere difficile l'allocazione di blocchi contigui di memoria da parte del Garbage Collector. Se è stato aggiunto un numero elevato di oggetti in memoria, ad esempio usando l'istruzione fixed in C# o chiamando il GCHandle.Alloc(Object, GCHandleType) metodo con un tipo di handle di GCHandleType.Pinned, è possibile eseguire le operazioni seguenti per risolvere l'eccezione OutOfMemoryException .

  • Valutare se ogni oggetto deve essere effettivamente aggiunto,

  • Assicurarsi che ogni oggetto venga rimosso il prima possibile.

  • Assicurarsi che ogni chiamata al GCHandle.Alloc(Object, GCHandleType) metodo per aggiungere memoria abbia una chiamata corrispondente al GCHandle.Free metodo per rimuovere tale memoria.

Le istruzioni MSIL (Microsoft Intermediate) seguenti generano un'eccezione OutOfMemoryException :

Costruttori

OutOfMemoryException()

Inizializza una nuova istanza della classe OutOfMemoryException.

OutOfMemoryException(SerializationInfo, StreamingContext)

Inizializza una nuova istanza della classe OutOfMemoryException con dati serializzati.

OutOfMemoryException(String)

Inizializza una nuova istanza della classe OutOfMemoryException con un messaggio di errore specificato.

OutOfMemoryException(String, Exception)

Inizializza una nuova istanza della classe OutOfMemoryException con un messaggio di errore specificato e un riferimento all'eccezione interna che è la causa dell'eccezione corrente.

Proprietà

Data

Ottiene una raccolta di coppie chiave/valore che forniscono informazioni definite dall'utente aggiuntive sull'eccezione.

(Ereditato da Exception)
HelpLink

Ottiene o imposta un collegamento al file della Guida associato all'eccezione.

(Ereditato da Exception)
HResult

Ottiene o imposta HRESULT, un valore numerico codificato che viene assegnato a un'eccezione specifica.

(Ereditato da Exception)
InnerException

Ottiene l'istanza di Exception che ha causato l'eccezione corrente.

(Ereditato da Exception)
Message

Ottiene un messaggio che descrive l'eccezione corrente.

(Ereditato da Exception)
Source

Ottiene o imposta il nome dell'oggetto o dell'applicazione che ha generato l'errore.

(Ereditato da Exception)
StackTrace

Ottiene una rappresentazione di stringa dei frame immediati nello stack di chiamate.

(Ereditato da Exception)
TargetSite

Ottiene il metodo che genera l'eccezione corrente.

(Ereditato da Exception)

Metodi

Equals(Object)

Determina se l'oggetto specificato è uguale all'oggetto corrente.

(Ereditato da Object)
GetBaseException()

Quando ne viene eseguito l'override in una classe derivata, restituisce l'Exception che è la causa radice di una o più eccezioni successive.

(Ereditato da Exception)
GetHashCode()

Funge da funzione hash predefinita.

(Ereditato da Object)
GetObjectData(SerializationInfo, StreamingContext)

Quando ne viene eseguito l'override in una classe derivata, imposta il controllo SerializationInfo con le informazioni sull'eccezione.

(Ereditato da Exception)
GetType()

Ottiene il tipo di runtime dell'istanza corrente.

(Ereditato da Exception)
MemberwiseClone()

Crea una copia superficiale dell'oggetto Object corrente.

(Ereditato da Object)
ToString()

Crea e restituisce una rappresentazione di stringa dell'eccezione corrente.

(Ereditato da Exception)

Eventi

SerializeObjectState
Obsoleta.

Si verifica quando un'eccezione viene serializzata per creare un oggetto di stato eccezione contenente i dati serializzati relativi all'eccezione.

(Ereditato da Exception)

Si applica a

Vedi anche