Fuite de mémoire C#

王林
王林original
2024-09-03 15:21:56421parcourir

Une fuite de mémoire est une situation qui se produit lorsqu’un programme ou une application utilise la mémoire principale du système sur une longue période. Lorsque le programme ne libère pas la mémoire qu'il occupe pendant l'exécution, même après avoir terminé son processus d'exécution, cet espace mémoire alloué dégrade les performances du système et peut le rendre insensible. Dans cette rubrique, nous allons en apprendre davantage sur les fuites de mémoire C#.

Il est de la responsabilité d'un ramasse-miettes de libérer la mémoire allouée inutilisée, mais nous rencontrons toujours le problème de fuite de mémoire car nous référençons parfois l'objet inutilisé à partir d'une variable qui ne sort jamais de portée tout au long de la vie de l'application.

Syntaxe

Il existe de nombreuses façons d’éviter les fuites de mémoire en C# ; nous pouvons éviter les fuites de mémoire lorsque nous travaillons avec des ressources non gérées à l'aide de l'instruction « using », qui appelle en interne la méthode Dispose(). La syntaxe de l'instruction « using » est la suivante :

using(var  objectName = new AnyDisposableType)
{
//user code
}

Dans les instructions ci-dessus, « var » est le mot-clé utilisé pour stocker tout type de données, et le compilateur peut déterminer ce type de données au moment de la compilation. « objectName » est n’importe quel nom défini par l’utilisateur pour l’objet. 'new' est le mot-clé utilisé pour initialiser l'objet et 'AnyDisposableType' peut être n'importe quelle classe comme StreamReader, BinaryReader, SqlConnection, etc. dont l'objet peut être supprimé à l'aide de l'instruction 'using'.

Comment fonctionne la fuite de mémoire en C# ?

Pour les applications .NET, nous disposons d'un garbage collector pour éliminer la mémoire inutilisée, mais nous rencontrons quand même le problème des fuites de mémoire. Cela ne signifie pas que le garbage collector ne fonctionne pas correctement, mais cela se produit en raison d'une certaine ignorance de la part du programmeur.

Supposons que nous ignorions les fuites de mémoire dans notre application pendant une très longue période. Dans ce cas, nous augmentons la consommation de mémoire de notre application, ce qui dégrade les performances de notre application et peut la détruire progressivement, donnant l'exception OutOfMemoryException.

Il existe deux causes principales de fuite de mémoire en C# :

  • La première cause est d'avoir un objet inutilisé qui n'est plus nécessaire mais toujours référencé par une variable qui a sa portée tout au long de la vie de l'application. Puisque cet objet a une référence, il ne sera pas détruit par le ramasse-miettes et restera pour toujours en mémoire et peut devenir une cause de fuite de mémoire. Un exemple de cette situation peut être un événement que nous avons enregistré mais qui n'est jamais désenregistré.
  • La deuxième cause est d'allouer de la mémoire à des ressources non gérées et de ne pas la libérer après utilisation. Comme les ressources gérées, les ressources non gérées ne peuvent pas être récupérées automatiquement. Ainsi, il est de la responsabilité du programmeur de libérer cette mémoire après utilisation.

Certaines raisons provoquant une fuite de mémoire en C# sont les suivantes :

  • Lorsque l'on s'abonne à un événement, la classe publiant l'événement détient une référence à la classe qui y est abonnée. De ce fait, le garbage collector ne supprimera pas l'objet de la classe qui s'est abonnée à l'événement, et en même temps, si le programmeur ne désabonne pas cet événement, cela entraînera une fuite de mémoire.
  • Capturer un membre de la classe dans une méthode anonyme peut entraîner une fuite de mémoire.
  • Les classes statiques et leurs variables statiques associées et tout ce qui est référencé par ces variables statiques ne peuvent jamais être récupérés et peuvent entraîner une fuite de mémoire.
  • L'utilisation de la fonctionnalité de mise en cache pour une période indéfinie peut provoquer une fuite de mémoire.
  • Si nous avons un thread qui s'exécute à l'infini et qui n'a pas de tâche dans notre application mais des références à des objets, cela peut entraîner une fuite de mémoire.
  • Le garbage collector ne gère pas les ressources non gérées. Ainsi, ne pas disposer des ressources non gérées après leur utilisation peut entraîner une fuite de mémoire.

Exemples de fuite de mémoire C#

Différents exemples sont mentionnés ci-dessous :

Exemple n°1

Cet exemple montre un thread attendant de se terminer et peut donc devenir une cause de fuite de mémoire.

Code :

using System;
using System.Threading;
namespace ConsoleApp4
{
public class Program
{
public static void Main()
{
while (true)
{
Console.WriteLine("Press enter key to start new thread");
Console.ReadLine();
Thread thread = new Thread(new ThreadStart(StartThread));
thread.Start();
}
}
public static void StartThread()
{
Console.WriteLine("Thread " +
Thread.CurrentThread.ManagedThreadId + " started");
//Wait until current thread terminates
Thread.CurrentThread.Join();
}
}
}

Sortie :

Fuite de mémoire C#

Chaque fois que nous appuyons sur « Entrée » dans le programme ci-dessus, son utilisation de la mémoire augmente.

Exemple n°2

Exemple montrant l'utilisation de ressources non gérées à l'aide de l'instruction « using » pour éviter une fuite de mémoire.

Code :

using System;
using System.IO;
namespace ConsoleApp4
{
public class Program
{
public static void Main()
{
string filePath = @"E:\Content\memoryLeak.txt";
string content = string.Empty;
try
{
//writing file using StreamWriter
//making use of 'using' statement to dispose object after using it
using (StreamWriter writer = new StreamWriter(filePath))
{
writer.WriteLine("Learning C# programming");
}
//reading file using StreamReader
using (StreamReader streamReader = new StreamReader(filePath))
{
content = streamReader.ReadToEnd();
}
}
catch (Exception exception)
{
Console.WriteLine(exception.Message);
Console.ReadLine();
}
Console.WriteLine(content);
Console.ReadLine();
}
}
}

Sortie :

Fuite de mémoire C#

Fuite de mémoire C#

Comment éviter OutOfMemoryException en C# ?

Quelques points à garder à l'esprit pour éviter l'exception OutOfMemoryException due à une fuite de mémoire en C# :

  • Si nous nous sommes abonnés à un événement, nous devons désinscrire le gestionnaire d'événements de l'événement. Nous pouvons le faire en implémentant IDisposable.
  • Capturer la variable locale au lieu de la variable de classe dans la méthode anonyme peut éviter une fuite de mémoire.
  • En évitant l'utilisation excessive de variables statiques dans notre application, surtout lorsque ces variables sont de types référence, nous pouvons éviter la situation de fuite de mémoire.
  • Si nous disposons d'une fonctionnalité de mise en cache dans notre application, nous devons alors vider le cache régulièrement, surtout s'il n'est d'aucune utilité pendant une longue période. Nous pouvons également limiter la taille de la mise en cache et utiliser WeakReference pour stocker les objets mis en cache.
  • Une bonne gestion des threads dans les applications évite les fuites de mémoire.

Conclusion

Lorsqu'une application ne libère pas la mémoire qu'elle a utilisée lors de son exécution, cette mémoire sera bloquée et ne pourra être utilisée par aucun autre processus, entraînant une fuite de mémoire. Le garbage collector peut automatiquement supprimer les objets gérés mais ne peut pas supprimer les objets ou les ressources non gérés.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn