Partager via


OutOfMemoryException Classe

Définition

Exception levée quand il n'y a pas suffisamment de mémoire pour poursuivre l'exécution d'un programme.

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
Héritage
OutOfMemoryException
Héritage
OutOfMemoryException
Dérivé
Attributs

Remarques

OutOfMemoryException utilise HRESULT COR_E_OUTOFMEMORY, qui a la valeur 0x8007000E.

Pour obtenir la liste des valeurs initiales des propriétés d’une instance de OutOfMemoryException, consultez le OutOfMemoryException constructeurs.

Notes

La valeur de la propriété héritée Data est toujours null.

Une OutOfMemoryException exception a deux causes principales :

  • Vous tentez de développer un StringBuilder objet au-delà de la longueur définie par sa StringBuilder.MaxCapacity propriété.

  • Le Common Language Runtime ne peut pas allouer suffisamment de mémoire contiguë pour effectuer une opération. Cette exception peut être levée par n’importe quelle affectation de propriété ou appel de méthode qui nécessite une allocation de mémoire. Pour plus d’informations sur la cause de l’exception OutOfMemoryException , consultez le billet de blog « Mémoire insuffisante » Ne fait pas référence à la mémoire physique.

    Ce type d’exception OutOfMemoryException représente une défaillance catastrophique. Si vous choisissez de gérer l’exception, vous devez inclure un catch bloc qui appelle la Environment.FailFast méthode pour mettre fin à votre application et ajouter une entrée au journal des événements système, comme le fait l’exemple suivant.

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

Voici quelques-unes des conditions dans lesquelles l’exception est levée et les actions que vous pouvez effectuer pour l’éliminer :

Vous appelez la StringBuilder.Insert méthode.

Vous tentez d’augmenter la longueur d’un StringBuilder objet au-delà de la taille spécifiée par sa StringBuilder.MaxCapacity propriété. L’exemple suivant illustre l’exception OutOfMemoryException levée par un appel à la méthode lorsque l’exemple StringBuilder.Insert(Int32, String, Int32) tente d’insérer une chaîne qui entraînerait le dépassement de la capacité maximale de la propriété de Length l’objet.

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.

Vous pouvez effectuer l’une des opérations suivantes pour résoudre l’erreur :

Votre application s’exécute en tant que processus 32 bits.

Les processus 32 bits peuvent allouer un maximum de 2 Go de mémoire virtuelle en mode utilisateur sur les systèmes 32 bits et 4 Go de mémoire virtuelle en mode utilisateur sur les systèmes 64 bits. Cela peut rendre plus difficile pour le Common Language Runtime d’allouer suffisamment de mémoire contiguë lorsqu’une allocation importante est nécessaire. En revanche, les processus 64 bits peuvent allouer jusqu’à 8 To de mémoire virtuelle. Pour résoudre cette exception, recompilez votre application pour cibler une plateforme 64 bits. Pour plus d’informations sur le ciblage de plateformes spécifiques dans Visual Studio, consultez Guide pratique pour configurer des projets sur des plateformes cibles.

Votre application fuit des ressources non managées

Bien que le garbage collector soit en mesure de libérer la mémoire allouée aux types managés, il ne gère pas la mémoire allouée aux ressources non managées telles que les handles du système d’exploitation (y compris les handles vers les fichiers, les fichiers mappés en mémoire, les canaux, les clés de Registre et les poignées d’attente) et les blocs de mémoire alloués directement par les appels d’API Windows ou par les appels à des fonctions d’allocation de mémoire telles que malloc. Les types qui consomment des ressources non managées implémentent l’interface IDisposable .

Si vous consommez un type qui utilise des ressources non managées, veillez à appeler sa IDisposable.Dispose méthode lorsque vous avez terminé de l’utiliser. (Certains types implémentent également une Close méthode qui est identique en fonction à une Dispose méthode.) Pour plus d’informations, consultez la rubrique Utilisation d’objets qui implémentent IDisposable .

Si vous avez créé un type qui utilise des ressources non managées, vérifiez que vous avez implémenté le modèle Supprimer et, si nécessaire, fourni un finaliseur. Pour plus d’informations, consultez Implémentation d’une méthode Dispose et Object.Finalize.

Vous essayez de créer un grand tableau dans un processus 64 bits

Par défaut, le Common Language Runtime dans .NET Framework n’autorise pas les objets uniques dont la taille dépasse 2 Go. Pour remplacer cette valeur par défaut, vous pouvez utiliser le <paramètre de fichier de configuration gcAllowVeryLargeObjects> pour activer les tableaux dont la taille totale dépasse 2 Go. Sur .NET Core, la prise en charge des tableaux de plus de 2 Go est activée par défaut.

Vous utilisez de très grands ensembles de données (tels que des tableaux, des collections ou des jeux de données de base de données) en mémoire.

Lorsque les structures de données ou les jeux de données qui résident dans la mémoire deviennent si volumineux que le Common Language Runtime n’est pas en mesure d’allouer suffisamment de mémoire contiguë pour elles, une OutOfMemoryException exception se produit.

Pour éviter les OutOfMemoryException exceptions, vous devez modifier votre application afin que moins de données résident dans la mémoire, ou que les données soient divisées en segments qui nécessitent des allocations de mémoire plus petites. Exemple :

  • Si vous récupérez toutes les données d’une base de données, puis que vous les filtrez dans votre application pour réduire les déplacements vers le serveur, vous devez modifier vos requêtes pour renvoyer uniquement le sous-ensemble de données dont votre application a besoin. Lorsque vous travaillez avec des tables volumineuses, plusieurs requêtes sont presque toujours plus efficaces que la récupération de toutes les données dans une seule table, puis leur manipulation.

  • Si vous exécutez des requêtes que les utilisateurs créent dynamiquement, vous devez vous assurer que le nombre d’enregistrements retournés par la requête est limité.

  • Si vous utilisez des tableaux volumineux ou d’autres objets de collection dont la taille entraîne une OutOfMemoryException exception, vous devez modifier votre application pour utiliser les données dans des sous-ensembles plutôt que pour les utiliser en même temps.

L’exemple suivant obtient un tableau qui se compose de 200 millions de valeurs à virgule flottante, puis calcule leur moyenne. La sortie de l’exemple montre que, étant donné que l’exemple stocke l’ensemble du tableau en mémoire avant de calculer la moyenne, un OutOfMemoryException est levée.

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.

L’exemple suivant élimine l’exception OutOfMemoryException en traitant les données entrantes sans stocker l’ensemble du jeu de données en mémoire, en sérialisant les données dans un fichier si nécessaire pour permettre un traitement ultérieur (ces lignes sont commentées dans l’exemple, car dans ce cas, elles produisent un fichier dont la taille est supérieure à 1 Go) et en renvoyant la moyenne calculée et le nombre de cas à la routine appelante.

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

Vous concatènez à plusieurs reprises des chaînes volumineuses.

Étant donné que les chaînes sont immuables, chaque opération de concaténation de chaîne crée une chaîne. L’impact pour les petites chaînes, ou pour un petit nombre d’opérations de concaténation, est négligeable. Toutefois, pour les chaînes volumineuses ou un très grand nombre d’opérations de concaténation, la concaténation de chaînes peut entraîner un grand nombre d’allocations de mémoire et une fragmentation de la mémoire, des performances médiocres et éventuellement des OutOfMemoryException exceptions.

Lors de la concaténation de chaînes volumineuses ou de l’exécution d’un grand nombre d’opérations de concaténation, vous devez utiliser la StringBuilder classe au lieu de la String classe . Une fois que vous avez terminé de manipuler la chaîne, convertissez l’instance StringBuilder en chaîne en appelant la StringBuilder.ToString méthode .

Vous épinglez un grand nombre d’objets en mémoire.

L’épinglage d’un grand nombre d’objets en mémoire pendant de longues périodes peut rendre difficile pour le garbage collector d’allouer des blocs de mémoire contigus. Si vous avez épinglé un grand nombre d’objets en mémoire, par exemple en utilisant l’instruction fixed en C# ou en appelant la GCHandle.Alloc(Object, GCHandleType) méthode avec un type de handle de GCHandleType.Pinned, vous pouvez effectuer les opérations suivantes pour résoudre l’exception OutOfMemoryException .

  • Évaluer si chaque objet a vraiment besoin d’être épinglé,

  • Assurez-vous que chaque objet n’est pas épinglé dès que possible.

  • Assurez-vous que chaque appel à la méthode d’épingler la GCHandle.Alloc(Object, GCHandleType) mémoire a un appel correspondant à la GCHandle.Free méthode pour désépiner cette mémoire.

Les instructions microsoft intermédiaires (MSIL) suivantes lèvent une OutOfMemoryException exception :

Constructeurs

OutOfMemoryException()

Initialise une nouvelle instance de la classe OutOfMemoryException.

OutOfMemoryException(SerializationInfo, StreamingContext)
Obsolète.

Initialise une nouvelle instance de la classe OutOfMemoryException avec des données sérialisées.

OutOfMemoryException(String)

Initialise une nouvelle instance de la classe OutOfMemoryException avec un message d'erreur spécifié.

OutOfMemoryException(String, Exception)

Initialise une nouvelle instance de la classe OutOfMemoryException avec un message d'erreur spécifié et une référence à l'exception interne ayant provoqué cette exception.

Propriétés

Data

Obtient une collection de paires clé/valeur qui fournissent des informations définies par l'utilisateur supplémentaires sur l'exception.

(Hérité de Exception)
HelpLink

Obtient ou définit un lien vers le fichier d'aide associé à cette exception.

(Hérité de Exception)
HResult

Obtient ou définit HRESULT, valeur numérique codée qui est assignée à une exception spécifique.

(Hérité de Exception)
InnerException

Obtient l'instance Exception qui a provoqué l'exception actuelle.

(Hérité de Exception)
Message

Obtient un message qui décrit l'exception active.

(Hérité de Exception)
Source

Obtient ou définit le nom de l'application ou de l'objet qui est à l'origine de l'erreur.

(Hérité de Exception)
StackTrace

Obtient une représentation sous forme de chaîne des frames immédiats sur la pile des appels.

(Hérité de Exception)
TargetSite

Obtient la méthode qui lève l'exception actuelle.

(Hérité de Exception)

Méthodes

Equals(Object)

Détermine si l'objet spécifié est égal à l'objet actuel.

(Hérité de Object)
GetBaseException()

En cas de substitution dans une classe dérivée, retourne la Exception qui est à l'origine d'une ou de plusieurs exceptions ultérieures.

(Hérité de Exception)
GetHashCode()

Fait office de fonction de hachage par défaut.

(Hérité de Object)
GetObjectData(SerializationInfo, StreamingContext)
Obsolète.

En cas de substitution dans une classe dérivée, définit SerializationInfo avec des informations sur l'exception.

(Hérité de Exception)
GetType()

Obtient le type au moment de l'exécution de l'instance actuelle.

(Hérité de Exception)
MemberwiseClone()

Crée une copie superficielle du Object actuel.

(Hérité de Object)
ToString()

Crée et retourne une chaîne représentant l'exception actuelle.

(Hérité de Exception)

Événements

SerializeObjectState
Obsolète.

Se produit quand une exception est sérialisée pour créer un objet d'état d'exception qui contient des données sérialisées concernant l'exception.

(Hérité de Exception)

S’applique à

Voir aussi