OutOfMemoryException Classe

Definição

A exceção é lançada 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
[System.Serializable]
public class OutOfMemoryException : SystemException
[System.Serializable]
[System.Runtime.InteropServices.ComVisible(true)]
public class OutOfMemoryException : SystemException
public class OutOfMemoryException : SystemException
type OutOfMemoryException = class
    inherit Exception
[<System.Serializable>]
type OutOfMemoryException = class
    inherit SystemException
[<System.Serializable>]
[<System.Runtime.InteropServices.ComVisible(true)>]
type OutOfMemoryException = class
    inherit SystemException
type OutOfMemoryException = class
    inherit SystemException
Public Class OutOfMemoryException
Inherits Exception
Public Class OutOfMemoryException
Inherits SystemException
Herança
OutOfMemoryException
Herança
OutOfMemoryException
Derivado
Atributos

Observações

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

Para obter uma lista dos valores iniciais de propriedade de uma instância de OutOfMemoryException, consulte os construtores de OutOfMemoryException.

Note

O valor da propriedade herdada Data é sempre null.

Uma OutOfMemoryException exceção tem duas causas principais:

  • Está a tentar expandir um StringBuilder objeto para além do comprimento definido pela sua StringBuilder.MaxCapacity propriedade.

  • O runtime da linguagem comum não consegue alocar memória contígua suficiente para realizar uma operação com sucesso. Esta exceção pode ser lançada por qualquer atribuição de propriedade ou chamada de método que exija uma alocação de memória. Para mais informações sobre a causa da OutOfMemoryException exceção, consulte o artigo do blogue "Fora de Memória" Não Se Refere à Memória Física.

    Este tipo de OutOfMemoryException exceção representa uma falha catastrófica. Se optar por tratar a exceção, deve incluir um catch bloco que chame o Environment.FailFast método para terminar a sua aplicação e adicionar uma entrada ao registo de eventos do sistema, como faz o exemplo seguinte.

    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 em que a exceção é lançada e as ações que pode tomar para a eliminar incluem as seguintes:

Estás a chamar o StringBuilder.Insert método.

Está a tentar aumentar o comprimento de um StringBuilder objeto para além do tamanho especificado pela sua StringBuilder.MaxCapacity propriedade. O exemplo seguinte ilustra a OutOfMemoryException exceção lançada por uma chamada ao StringBuilder.Insert(Int32, String, Int32) método quando o exemplo tenta inserir uma cadeia que faria com que a propriedade do Length objeto excedesse a 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.

Pode fazer qualquer uma das seguintes opções para resolver o erro:

A sua aplicação corre como um processo de 32 bits.

Processos de 32 bits podem alocar um máximo de 2GB de memória virtual em modo utilizador em sistemas de 32 bits, e 4GB de memória virtual em modo utilizador em sistemas de 64 bits. Isto pode dificultar que o tempo de execução da linguagem comum aloque memória contígua suficiente quando é necessária uma grande alocação. Em contraste, os processos de 64 bits podem alocar até 8TB de memória virtual. Para resolver esta exceção, recompile a sua aplicação para direcionar uma plataforma de 64 bits. Para informações sobre como direcionar plataformas específicas em Visual Studio, veja Como: Configurar Projetos para Direcionar Plataformas.

A sua aplicação está a vazar recursos não geridos

Embora o coletor de lixo consiga libertar memória alocada a tipos geridos, não gere memória alocada a recursos não geridos, como handles do sistema operativo (incluindo handles para ficheiros, ficheiros mapeados em memória, pipes, chaves de registo e handles de espera) e blocos de memória alocados diretamente por chamadas de API Windows ou por chamadas para funções de alocação de memória como malloc. Os tipos que consomem recursos não geridos implementam a IDisposable interface.

Se estiver a consumir um tipo que utiliza recursos não geridos, deve certificar-se de chamar o seu IDisposable.Dispose método quando terminar de o usar. (Alguns tipos também implementam um Close método que é idêntico em função a um Dispose método.) Para mais informações, consulte o tópico Usar Objetos que Implementam IDisposável .

Se criou um tipo que utiliza recursos não geridos, certifique-se de que implementou o padrão Dispose e, se necessário, forneceu um finalizador. Para mais informações, consulte Implementar um método Dispose e Object.Finalize.

Está a tentar criar um grande array num processo de 64 bits

Por defeito, o tempo de execução da linguagem comum no .NET Framework não permite objetos únicos cujo tamanho exceda 2GB. Para sobrescrever este padrão, pode usar a <configuração gcAllowVeryLargeObjects> para ativar arrays cujo tamanho total exceda 2 GB. No .NET Core, o suporte para arrays superiores a 2 GB está ativado por defeito.

Está a trabalhar com conjuntos muito grandes de dados (como arrays, coleções ou conjuntos de dados de bases de dados) na memória.

Quando as estruturas de dados ou conjuntos de dados que residem na memória se tornam tão grandes que o tempo de execução da linguagem comum não consegue alocar memória contígua suficiente para elas, resulta uma OutOfMemoryException exceção.

Para evitar exceções OutOfMemoryException , deve modificar a sua aplicação para que menos dados residam na memória, ou os dados são divididos em segmentos que exigem alocações de memória menores. Por exemplo:

  • Se estiver a recuperar todos os dados de uma base de dados e depois a filtrá-los na sua aplicação para minimizar viagens ao servidor, deve modificar as suas consultas para devolver apenas o subconjunto de dados que a sua aplicação precisa. Quando se trabalha com tabelas grandes, múltiplas consultas são quase sempre mais eficientes do que recuperar todos os dados de uma única tabela e depois manipulá-los.

  • Se estiver a executar consultas que os utilizadores criam dinamicamente, deve garantir que o número de registos devolvidos pela consulta é limitado.

  • Se estiver a usar grandes arrays ou outros objetos de coleção cujo tamanho resulte numa OutOfMemoryException exceção, deve modificar a sua aplicação para trabalhar os dados em subconjuntos em vez de trabalhar com todos de uma vez.

O exemplo seguinte obtém um array que consiste em 200 milhões de valores de ponto flutuante e depois calcula a sua média. A saída do exemplo mostra que, como o exemplo armazena todo o array na memória antes de calcular a média, um OutOfMemoryException é lançado.

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 seguinte elimina a OutOfMemoryException exceção ao processar os dados recebidos sem armazenar todo o conjunto de dados na memória, serializando os dados para um ficheiro se necessário para permitir processamento adicional (estas linhas são comentadas no exemplo, pois neste caso produzem um ficheiro com tamanho superior a 1GB), e retornando a média calculada e o número de casos à 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

Estás a concatenar repetidamente cadeias grandes.

Como as cadeias são imutáveis, cada operação de concatenação cria uma nova cadeia. O impacto para cadeias pequenas, ou para um pequeno número de operações de concatenação, é negligenciável. Mas para cadeias grandes ou um número muito elevado de operações de concatenação, a concatenação de cadeias 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 grandes ou realizar um grande número de operações de concatenação, deve usar a StringBuilder classe em vez da String classe. Quando terminares de manipular a cadeia, converte a StringBuilder instância numa cadeia chamando o StringBuilder.ToString método.

Fixas um grande número de objetos na memória.

Fixar um grande número de objetos na memória durante longos períodos pode dificultar que o coletor de lixo aloque blocos contíguos de memória. Se 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 handle , GCHandleType.Pinnedpode fazer o seguinte para abordar a OutOfMemoryException exceção.

  • Avaliar se cada objeto realmente precisa de ser fixado,

  • Certifique-se de que cada objeto é desimobilizado o mais rapidamente possível.

  • Certifique-se de que cada chamada ao GCHandle.Alloc(Object, GCHandleType) método para fixar memória tem uma chamada correspondente ao GCHandle.Free método para desfixar essa memória.

As seguintes instruções Microsoft intermédias (MSIL) lançam uma exceção OutOfMemoryException:

Construtores

Name Description
OutOfMemoryException()

Inicializa uma nova instância da OutOfMemoryException classe.

OutOfMemoryException(SerializationInfo, StreamingContext)

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

OutOfMemoryException(String, Exception)

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

OutOfMemoryException(String)

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

Propriedades

Name Description
Data

Obtém uma coleção de pares chave/valor que fornecem informação adicional definida pelo utilizador sobre a exceção.

(Herdado de Exception)
HelpLink

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

(Herdado de Exception)
HResult

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

(Herdado de Exception)
InnerException

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

(Herdado de Exception)
Message

Recebe uma mensagem que descreve a exceção atual.

(Herdado de Exception)
Source

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

(Herdado de Exception)
StackTrace

Obtém uma representação string dos frames imediatos na stack de chamadas.

(Herdado de Exception)
TargetSite

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

(Herdado de Exception)

Métodos

Name Description
Equals(Object)

Determina se o objeto especificado é igual ao objeto atual.

(Herdado de Object)
GetBaseException()

Quando sobrescrito numa classe derivada, devolve o Exception que é a causa raiz de uma ou mais exceções subsequentes.

(Herdado de Exception)
GetHashCode()

Serve como função de hash predefinida.

(Herdado de Object)
GetObjectData(SerializationInfo, StreamingContext)

Quando sobreposto numa classe derivada, define a SerializationInfo informação com sobre a exceção.

(Herdado de Exception)
GetType()

Obtém o tipo de execução da instância atual.

(Herdado de Exception)
MemberwiseClone()

Cria uma cópia superficial do atual Object.

(Herdado de Object)
ToString()

Cria e devolve uma representação string da exceção atual.

(Herdado de Exception)

evento

Name Description
SerializeObjectState

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

Ver também