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 ha 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 si sceglie di gestire l'eccezione, è necessario includere un catch blocco che chiama il Environment.FailFast metodo per terminare l'app e aggiungere una voce al registro eventi di sistema, come illustrato 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 eliminarle 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 causerebbe 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.

È possibile eseguire una delle operazioni seguenti per risolvere l'errore:

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 per indirizzare una piattaforma a 64 bit. Per informazioni sulla destinazione di piattaforme specifiche in Visual Studio, vedere Procedura: Configurare progetti in 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 alle risorse non gestite, ad esempio handle del sistema operativo (inclusi handle ai file, file mappati alla memoria, pipe, chiavi del Registro di sistema e handle di attesa) e blocchi di memoria allocati direttamente dalle chiamate API Windows o dalle chiamate alle funzioni di allocazione della memoria, ad esempio malloc. I tipi che usano risorse non gestite implementano l'interfaccia IDisposable .

Se si usa un tipo che usa risorse non gestite, è necessario assicurarsi di chiamare il IDisposable.Dispose relativo 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 Uso di oggetti che implementano 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 2 GB. Per eseguire l'override di questa impostazione predefinita, è possibile usare l'impostazione <del file di configurazione gcAllowVeryLargeObjects> per abilitare le matrici le cui dimensioni totali superano 2 GB. In .NET Core il supporto per le matrici di dimensioni superiori a 2 GB è abilitato per impostazione predefinita.

Si riguardano 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 per loro, un'eccezione OutOfMemoryException risultati.

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

  • Se si recuperano tutti i dati da un database e quindi lo si filtra nell'app per ridurre al minimo i viaggi al server, è necessario 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 che gli utenti creano dinamicamente, è 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 per lavorare i dati nei 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 la cui dimensione è maggiore di 1 GB) e restituisce la media calcolata e il numero di casi 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 sono non modificabili, ogni operazione di concatenazione stringa crea una nuova stringa. L'impatto per stringhe piccole 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, la concatenazione di stringhe può causare un numero elevato di allocazioni di memoria e frammentazione della memoria, prestazioni ridotte e possibilmente OutOfMemoryException eccezioni.

Quando si concatenano stringhe di grandi dimensioni o si eseguono un numero elevato di operazioni di concatenazione, è consigliabile usare la classe anziché la StringBuilderString 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 periodi lunghi 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 aggiunto in realtà,

  • Assicurarsi che ogni oggetto venga rimosso il prima possibile.

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

Le istruzioni microsoft intermedie (MSIL) seguenti generano un'eccezione OutOfMemoryException :

Costruttori

OutOfMemoryException()

Inizializza una nuova istanza della classe OutOfMemoryException.

OutOfMemoryException(SerializationInfo, StreamingContext)
Obsoleti.

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

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

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