Condividi tramite


OutOfMemoryException Classe

Definizione

Eccezione generata quando non è disponibile 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 dei valori iniziali delle proprietà per un'istanza di OutOfMemoryException, consultare i costruttori di OutOfMemoryException.

Annotazioni

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 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 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 comporterebbe 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 dalle chiamate API di Windows o dalle chiamate alle funzioni di allocazione della memoria, mallocad esempio . I tipi che utilizzano risorse non gestite implementano l'interfaccia IDisposable .

Se si utilizza 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 in 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 i 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 matrici di dimensioni maggiori di 2 GB è abilitato per impostazione predefinita.

Si lavora con 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, 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. Per 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 in modo da restituire solo il subset di dati necessari all'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 raccolta le cui dimensioni generano un'eccezione OutOfMemoryException , è necessario modificare l'applicazione in modo da usare 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 .

Si aggiunge 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 Microsoft Intermediate (MSIL) seguenti generano un'eccezione OutOfMemoryException :

Costruttori

Nome Descrizione
OutOfMemoryException()

Inizializza una nuova istanza della classe OutOfMemoryException.

OutOfMemoryException(SerializationInfo, StreamingContext)
Obsoleti.

Inizializza una nuova istanza della OutOfMemoryException classe con dati serializzati.

OutOfMemoryException(String, Exception)

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

OutOfMemoryException(String)

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

Proprietà

Nome Descrizione
Data

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

(Ereditato da Exception)
HelpLink

Ottiene o imposta un collegamento al file della Guida associato a questa eccezione.

(Ereditato da Exception)
HResult

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

(Ereditato da Exception)
InnerException

Ottiene l'istanza 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'applicazione o dell'oggetto che causa l'errore.

(Ereditato da Exception)
StackTrace

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

(Ereditato da Exception)
TargetSite

Ottiene il metodo che genera l'eccezione corrente.

(Ereditato da Exception)

Metodi

Nome Descrizione
Equals(Object)

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

(Ereditato da Object)
GetBaseException()

Quando sottoposto a override in una classe derivata, restituisce l'oggetto Exception che rappresenta 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.

In caso di override in una classe derivata, imposta con le SerializationInfo informazioni sull'eccezione.

(Ereditato da Exception)
GetType()

Ottiene il tipo di runtime dell'istanza corrente.

(Ereditato da Exception)
MemberwiseClone()

Crea una copia superficiale del Objectcorrente.

(Ereditato da Object)
ToString()

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

(Ereditato da Exception)

Eventi

Nome Descrizione
SerializeObjectState
Obsoleti.

Si verifica quando viene serializzata un'eccezione per creare un oggetto stato dell'eccezione contenente dati serializzati sull'eccezione.

(Ereditato da Exception)

Si applica a

Vedi anche