Compartir vía


OutOfMemoryException Clase

Definición

Excepción que se produce cuando no hay suficiente memoria para continuar la ejecución de un programa.

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
Herencia
OutOfMemoryException
Herencia
OutOfMemoryException
Derivado
Atributos

Comentarios

OutOfMemoryException usa el COR_E_OUTOFMEMORYHRESULT , que tiene el valor 0x8007000E.

Para obtener una lista de valores de propiedad iniciales para una instancia de OutOfMemoryException, vea los constructores de OutOfMemoryException.

Nota

El valor de la propiedad Data heredada siempre es null.

Una excepción de OutOfMemoryException tiene dos causas principales:

  • Está intentando expandir un objeto StringBuilder más allá de la longitud definida por su propiedad StringBuilder.MaxCapacity.

  • Common Language Runtime no puede asignar suficiente memoria contigua para realizar correctamente una operación. Esta excepción se puede producir mediante cualquier llamada de método o asignación de propiedades que requiera una asignación de memoria. Para obtener más información sobre la causa de la excepción de OutOfMemoryException, consulte la entrada de blog "Memoria insuficiente" No hace referencia a la memoria física.

    Este tipo de excepción de OutOfMemoryException representa un error catastrófico. Si decide controlar la excepción, debe incluir un bloque de catch que llame al método Environment.FailFast para finalizar la aplicación y agregar una entrada al registro de eventos del sistema, como hace el ejemplo siguiente.

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

Algunas de las condiciones en las que se produce la excepción y las acciones que puede realizar para eliminarla incluyen las siguientes:

Está llamando al método StringBuilder.Insert.

Está intentando aumentar la longitud de un objeto de StringBuilder más allá del tamaño especificado por su propiedad StringBuilder.MaxCapacity. En el ejemplo siguiente se muestra la excepción de OutOfMemoryException producida por una llamada al método StringBuilder.Insert(Int32, String, Int32) cuando el ejemplo intenta insertar una cadena que haría que la propiedad Length del objeto supere su capacidad máxima.

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.

Puede realizar cualquiera de las siguientes acciones para solucionar el error:

La aplicación se ejecuta como un proceso de 32 bits.

Los procesos de 32 bits pueden asignar un máximo de 2 GB de memoria en modo usuario virtual en sistemas de 32 bits y 4 GB de memoria en modo de usuario virtual en sistemas de 64 bits. Esto puede dificultar que Common Language Runtime asigne suficiente memoria contigua cuando se necesite una asignación grande. En cambio, los procesos de 64 bits pueden asignar hasta 8 TB de memoria virtual. Para solucionar esta excepción, vuelva a compilar la aplicación para tener como destino una plataforma de 64 bits. Para obtener información sobre el destino de plataformas específicas en Visual Studio, consulte Cómo: Configurar proyectos en plataformas de destino.

La aplicación está filtrando recursos no administrados

Aunque el recolector de elementos no utilizados puede liberar memoria asignada a tipos administrados, no administra la memoria asignada a recursos no administrados, como identificadores del sistema operativo (incluidos identificadores de archivos, archivos asignados a memoria, canalizaciones, claves del Registro y controladores de espera) y bloques de memoria asignados directamente por llamadas api de Windows o por llamadas a funciones de asignación de memoria, como malloc. Los tipos que consumen recursos no administrados implementan la interfaz IDisposable.

Si usa un tipo que usa recursos no administrados, debe asegurarse de llamar a su método IDisposable.Dispose cuando haya terminado de usarlo. (Algunos tipos también implementan un método Close idéntico en función a un método Dispose). Para obtener más información, vea el tema Using Objects That Implement IDisposable .

Si ha creado un tipo que usa recursos no administrados, asegúrese de que ha implementado el patrón Dispose y, si es necesario, proporcionó un finalizador. Para obtener más información, vea Implementación de un método Dispose y Object.Finalize.

Está intentando crear una matriz grande en un proceso de 64 bits

De forma predeterminada, Common Language Runtime en .NET Framework no permite objetos únicos cuyo tamaño supere los 2 GB. Para invalidar este valor predeterminado, puede usar la configuración del archivo de configuración gcAllowVeryLargeObjects de para habilitar matrices cuyo tamaño total supere los 2 GB. En .NET Core, la compatibilidad con matrices de más de 2 GB está habilitada de forma predeterminada.

Está trabajando con conjuntos de datos muy grandes (como matrices, colecciones o conjuntos de datos de base de datos) en memoria.

Cuando las estructuras de datos o los conjuntos de datos que residen en la memoria se vuelven tan grandes que Common Language Runtime no puede asignar suficiente memoria contigua para ellos, se produce una excepción de OutOfMemoryException.

Para evitar las excepciones de OutOfMemoryException, debe modificar la aplicación para que menos datos resida en la memoria o los datos se divida en segmentos que requieran asignaciones de memoria más pequeñas. Por ejemplo:

  • Si va a recuperar todos los datos de una base de datos y, a continuación, filtrarlos en la aplicación para minimizar los viajes al servidor, debe modificar las consultas para devolver solo el subconjunto de datos que necesita la aplicación. Al trabajar con tablas grandes, varias consultas casi siempre son más eficaces que recuperar todos los datos de una sola tabla y, a continuación, manipularlos.

  • Si está ejecutando consultas que los usuarios crean dinámicamente, debe asegurarse de que el número de registros devueltos por la consulta es limitado.

  • Si usa matrices grandes u otros objetos de colección cuyo tamaño da como resultado una excepción de OutOfMemoryException, debe modificar la aplicación para que funcione los datos en subconjuntos en lugar de trabajar con él todo a la vez.

En el ejemplo siguiente se obtiene una matriz que consta de 200 millones de valores de punto flotante y, a continuación, calcula su media. La salida del ejemplo muestra que, dado que el ejemplo almacena toda la matriz en memoria antes de calcular la media, se produce un 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.

En el ejemplo siguiente se elimina la excepción de OutOfMemoryException procesando los datos entrantes sin almacenar todo el conjunto de datos en memoria, serializando los datos en un archivo si es necesario para permitir el procesamiento adicional (estas líneas se comentan en el ejemplo, ya que en este caso generan un archivo cuyo tamaño es mayor que 1 GB) y devuelven la media calculada y el número de casos a la rutina de llamada.

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

Se concatenan repetidamente cadenas grandes.

Dado que las cadenas son inmutables, cada operación de concatenación de cadenas crea una nueva cadena. El impacto de cadenas pequeñas, o para un pequeño número de operaciones de concatenación, es insignificante. Pero para cadenas grandes o un gran número de operaciones de concatenación, la concatenación de cadenas puede provocar un gran número de asignaciones de memoria y fragmentación de memoria, un rendimiento deficiente y, posiblemente, OutOfMemoryException excepciones.

Al concatenar cadenas grandes o realizar un gran número de operaciones de concatenación, debe usar la clase StringBuilder en lugar de la clase String. Cuando haya terminado de manipular la cadena, convierta la instancia de StringBuilder en una cadena llamando al método StringBuilder.ToString.

anclar un gran número de objetos en memoria.

Anclar un gran número de objetos en memoria durante largos períodos puede dificultar que el recolector de elementos no utilizados asigne bloques contiguos de memoria. Si ha anclado un gran número de objetos en memoria, por ejemplo, mediante la instrucción fixed en C# o llamando al método GCHandle.Alloc(Object, GCHandleType) con un tipo de identificador de GCHandleType.Pinned, puede hacer lo siguiente para abordar la excepción OutOfMemoryException.

  • Evalúe si cada objeto realmente debe anclarse,

  • Asegúrese de que cada objeto esté desanclado lo antes posible.

  • Asegúrese de que cada llamada al método GCHandle.Alloc(Object, GCHandleType) para anclar la memoria tiene una llamada correspondiente al método GCHandle.Free para desanclar esa memoria.

Las siguientes instrucciones intermedias de Microsoft (MSIL) inician una excepción de OutOfMemoryException:

Constructores

OutOfMemoryException()

Inicializa una nueva instancia de la clase OutOfMemoryException.

OutOfMemoryException(SerializationInfo, StreamingContext)
Obsoletos.

Inicializa una nueva instancia de la clase OutOfMemoryException con datos serializados.

OutOfMemoryException(String, Exception)

Inicializa una nueva instancia de la clase OutOfMemoryException con un mensaje de error especificado y una referencia a la excepción interna que es la causa de esta excepción.

OutOfMemoryException(String)

Inicializa una nueva instancia de la clase OutOfMemoryException con un mensaje de error especificado.

Propiedades

Data

Obtiene una colección de pares clave-valor que proporcionan información adicional definida por el usuario sobre la excepción.

(Heredado de Exception)
HelpLink

Obtiene o establece un vínculo al archivo de ayuda asociado a esta excepción.

(Heredado de Exception)
HResult

Obtiene o establece HRESULT, un valor numérico codificado que se asigna a una excepción específica.

(Heredado de Exception)
InnerException

Obtiene la instancia de Exception que provocó la excepción actual.

(Heredado de Exception)
Message

Obtiene un mensaje que describe la excepción actual.

(Heredado de Exception)
Source

Obtiene o establece el nombre de la aplicación o el objeto que provoca el error.

(Heredado de Exception)
StackTrace

Obtiene una representación de cadena de los fotogramas inmediatos en la pila de llamadas.

(Heredado de Exception)
TargetSite

Obtiene el método que produce la excepción actual.

(Heredado de Exception)

Métodos

Equals(Object)

Determina si el objeto especificado es igual al objeto actual.

(Heredado de Object)
GetBaseException()

Cuando se reemplaza en una clase derivada, devuelve el Exception que es la causa principal de una o varias excepciones posteriores.

(Heredado de Exception)
GetHashCode()

Actúa como función hash predeterminada.

(Heredado de Object)
GetObjectData(SerializationInfo, StreamingContext)
Obsoletos.

Cuando se reemplaza en una clase derivada, establece el SerializationInfo con información sobre la excepción.

(Heredado de Exception)
GetType()

Obtiene el tipo de tiempo de ejecución de la instancia actual.

(Heredado de Exception)
MemberwiseClone()

Crea una copia superficial del Objectactual.

(Heredado de Object)
ToString()

Crea y devuelve una representación de cadena de la excepción actual.

(Heredado de Exception)

Eventos

SerializeObjectState
Obsoletos.

Se produce cuando se serializa una excepción para crear un objeto de estado de excepción que contiene datos serializados sobre la excepción.

(Heredado de Exception)

Se aplica a

Consulte también