Compartilhar via


OutOfMemoryException Classe

Definição

A exceção que é gerada quando não há memória suficiente para continuar a execução de um 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
Herança
OutOfMemoryException
Herança
OutOfMemoryException
Derivado
Atributos

Comentários

OutOfMemoryException usa o HRESULT COR_E_OUTOFMEMORY, que tem o valor 0x8007000E.

Para obter uma lista de valores de propriedade inicial para uma instância do OutOfMemoryException, consulte o OutOfMemoryException construtores.

Observação

O valor da propriedade herdada Data é sempre null.

Uma OutOfMemoryException exceção tem duas causas principais:

  • Você está tentando expandir um StringBuilder objeto além do comprimento definido por sua StringBuilder.MaxCapacity propriedade.

  • O Common Language Runtime não pode alocar memória contígua suficiente para executar uma operação com êxito. Essa exceção pode ser gerada por qualquer atribuição de propriedade ou chamada de método que exija uma alocação de memória. Para obter mais informações sobre a causa da OutOfMemoryException exceção, consulte a postagem no blog "Memória Insuficiente" Não Se Refere à Memória Física.

    Esse tipo de OutOfMemoryException exceção representa uma falha catastrófica. Se você optar por manipular a exceção, deverá incluir um catch bloco que chama o Environment.FailFast método para encerrar seu aplicativo e adicionar uma entrada ao log de eventos do sistema, como faz o exemplo a seguir.

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

Algumas das condições sob as quais a exceção é lançada e as ações que você pode tomar para eliminá-la incluem o seguinte:

Você está chamando o StringBuilder.Insert método .

Você está tentando aumentar o comprimento de um StringBuilder objeto além do tamanho especificado por sua StringBuilder.MaxCapacity propriedade. O exemplo a seguir ilustra a OutOfMemoryException exceção gerada por uma chamada ao StringBuilder.Insert(Int32, String, Int32) método quando o exemplo tenta inserir uma cadeia de caracteres que faria com que a propriedade do Length objeto excedesse sua capacidade 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.

Você pode fazer qualquer um dos seguintes procedimentos para resolver o erro:

Seu aplicativo é executado como um processo de 32 bits.

Processos de 32 bits podem alocar um máximo de 2 GB de memória do modo de usuário virtual em sistemas de 32 bits e 4 GB de memória do modo de usuário virtual em sistemas de 64 bits. Isso pode tornar mais difícil para o common language runtime alocar memória contígua suficiente quando uma alocação grande é necessária. Por outro lado, os processos de 64 bits podem alocar até 8 TB de memória virtual. Para resolver essa exceção, recompile seu aplicativo para direcionar uma plataforma de 64 bits. Para obter informações sobre como direcionar plataformas específicas no Visual Studio, consulte Como configurar projetos para plataformas de destino.

Seu aplicativo está vazando recursos não gerenciados

Embora o coletor de lixo seja capaz de liberar memória alocada para tipos gerenciados, ele não gerencia a memória alocada para recursos não gerenciados, como identificadores do sistema operacional (incluindo identificadores para arquivos, arquivos mapeados em memória, pipes, chaves do Registro e identificadores de espera) e blocos de memória alocados diretamente por chamadas à API do Windows ou por chamadas a funções de alocação de memória, como malloc. Os tipos que consomem recursos não gerenciados implementam a IDisposable interface .

Se você estiver consumindo um tipo que usa recursos não gerenciados, chame seu IDisposable.Dispose método quando terminar de usá-lo. (Alguns tipos também implementam um Close método idêntico na função a um Dispose método .) Para obter mais informações, consulte o tópico Usando objetos que implementam IDisposable .

Se você criou um tipo que usa recursos não gerenciados, verifique se implementou o padrão Dispose e, se necessário, forneceu um finalizador. Para obter mais informações, consulte Implementando um método Dispose e Object.Finalize.

Você está tentando criar uma matriz grande em um processo de 64 bits

Por padrão, o common language runtime no .NET Framework não permite objetos únicos cujo tamanho excede 2 GB. Para substituir esse padrão, você pode usar a configuração do <arquivo de configuração gcAllowVeryLargeObjects> para habilitar matrizes cujo tamanho total excede 2 GB. No .NET Core, o suporte para matrizes com mais de 2 GB está habilitado por padrão.

Você está trabalhando com conjuntos muito grandes de dados (como matrizes, coleções ou conjuntos de dados de banco de dados) na memória.

Quando estruturas de dados ou conjuntos de dados que residem na memória se tornam tão grandes que o Common Language Runtime não consegue alocar memória contígua suficiente para eles, uma exceção OutOfMemoryException resulta.

Para evitar as OutOfMemoryException exceções, você deve modificar seu aplicativo para que menos dados residam na memória ou os dados sejam divididos em segmentos que exigem alocações de memória menores. Por exemplo:

  • Se você estiver recuperando todos os dados de um banco de dados e filtrando-os em seu aplicativo para minimizar as viagens ao servidor, modifique suas consultas para retornar apenas o subconjunto de dados de que seu aplicativo precisa. Ao trabalhar com tabelas grandes, várias consultas são quase sempre mais eficientes do que recuperar todos os dados em uma única tabela e, em seguida, manipulá-los.

  • Se você estiver executando consultas que os usuários criam dinamicamente, verifique se o número de registros retornados pela consulta é limitado.

  • Se você estiver usando grandes matrizes ou outros objetos de coleção cujo tamanho resulta em uma exceção OutOfMemoryException , modifique seu aplicativo para trabalhar os dados em subconjuntos em vez de trabalhar com tudo de uma vez.

O exemplo a seguir obtém uma matriz que consiste em 200 milhões de valores de ponto flutuante e, em seguida, calcula sua média. A saída do exemplo mostra que, como o exemplo armazena toda a matriz na memória antes de calcular a média, um OutOfMemoryException é gerado.

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.

O exemplo a seguir elimina a OutOfMemoryException exceção processando os dados de entrada sem armazenar todo o conjunto de dados na memória, serializando os dados em um arquivo, se necessário, para permitir processamento adicional (essas linhas são comentadas no exemplo, pois, nesse caso, produzem um arquivo cujo tamanho é maior que 1 GB) e retornando a média calculada e o número de casos para a rotina de chamada.

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

Você está concatenando repetidamente cadeias de caracteres grandes.

Como as cadeias de caracteres são imutáveis, cada operação de concatenação de cadeia de caracteres cria uma nova cadeia de caracteres. O impacto para cadeias de caracteres pequenas ou para um pequeno número de operações de concatenação é insignificante. Mas para cadeias de caracteres grandes ou um número muito grande de operações de concatenação, a concatenação de cadeia de caracteres pode levar a um grande número de alocações de memória e fragmentação de memória, baixo desempenho e possivelmente OutOfMemoryException exceções.

Ao concatenar cadeias de caracteres grandes ou executar um grande número de operações de concatenação, você deve usar a StringBuilder classe em vez da String classe . Quando terminar de manipular a cadeia de caracteres, converta a StringBuilder instância em uma cadeia de caracteres chamando o StringBuilder.ToString método .

Você fixa um grande número de objetos na memória.

Fixar um grande número de objetos na memória por longos períodos pode dificultar a alocação de blocos contíguos de memória pelo coletor de lixo. Se você fixou um grande número de objetos na memória, por exemplo, usando a fixed instrução em C# ou chamando o GCHandle.Alloc(Object, GCHandleType) método com um tipo de identificador de GCHandleType.Pinned, poderá fazer o seguinte para resolver a OutOfMemoryException exceção.

  • Avalie se cada objeto realmente precisa ser fixado,

  • Certifique-se de que cada objeto seja desafixado o mais rápido possível.

  • Verifique se cada chamada ao método para GCHandle.Alloc(Object, GCHandleType) fixar memória tem uma chamada correspondente ao método para GCHandle.Free desafixar essa memória.

As seguintes instruções microsoft intermediate (MSIL) geram uma exceção OutOfMemoryException :

Construtores

OutOfMemoryException()

Inicializa uma nova instância da classe OutOfMemoryException.

OutOfMemoryException(SerializationInfo, StreamingContext)
Obsoleto.

Inicializa uma nova instância da classe OutOfMemoryException com dados serializados.

OutOfMemoryException(String)

Inicializa uma nova instância da classe OutOfMemoryException com uma mensagem de erro especificada.

OutOfMemoryException(String, Exception)

Inicializa uma nova instância da classe OutOfMemoryException com uma mensagem de erro especificada e uma referência à exceção interna que é a causa da exceção.

Propriedades

Data

Obtém uma coleção de pares de chave/valor que fornecem informações definidas pelo usuário adicionais sobre a exceção.

(Herdado de Exception)
HelpLink

Obtém ou define um link para o arquivo de ajuda associado a essa exceção.

(Herdado de Exception)
HResult

Obtém ou define HRESULT, um valor numérico codificado que é atribuído a uma exceção específica.

(Herdado de Exception)
InnerException

Obtém a instância Exception que causou a exceção atual.

(Herdado de Exception)
Message

Obtém uma mensagem que descreve a exceção atual.

(Herdado de Exception)
Source

Obtém ou define o nome do aplicativo ou objeto que causa o erro.

(Herdado de Exception)
StackTrace

Obtém uma representação de cadeia de caracteres de quadros imediatos na pilha de chamadas.

(Herdado de Exception)
TargetSite

Obtém o método que gerou a exceção atual.

(Herdado de Exception)

Métodos

Equals(Object)

Determina se o objeto especificado é igual ao objeto atual.

(Herdado de Object)
GetBaseException()

Quando substituído em uma classe derivada, retorna a Exception que é a causa raiz de uma ou mais exceções subsequentes.

(Herdado de Exception)
GetHashCode()

Serve como a função de hash padrão.

(Herdado de Object)
GetObjectData(SerializationInfo, StreamingContext)
Obsoleto.

Quando substituído em uma classe derivada, define o SerializationInfo com informações sobre a exceção.

(Herdado de Exception)
GetType()

Obtém o tipo de runtime da instância atual.

(Herdado de Exception)
MemberwiseClone()

Cria uma cópia superficial do Object atual.

(Herdado de Object)
ToString()

Cria e retorna uma representação de cadeia de caracteres da exceção atual.

(Herdado de Exception)

Eventos

SerializeObjectState
Obsoleto.

Ocorre quando uma exceção é serializada para criar um objeto de estado de exceção que contém dados serializados sobre a exceção.

(Herdado de Exception)

Aplica-se a

Confira também