Heim  >  Artikel  >  Backend-Entwicklung  >  C#-Speicherleck

C#-Speicherleck

王林
王林Original
2024-09-03 15:21:56397Durchsuche

Ein Speicherverlust ist eine Situation, die auftritt, wenn ein Programm oder eine Anwendung über einen längeren Zeitraum den Primärspeicher des Systems nutzt. Wenn das Programm den von ihm während der Ausführung belegten Speicher auch nach Abschluss des Ausführungsprozesses nicht freigibt, beeinträchtigt dieser zugewiesene Speicherplatz die Leistung des Systems und kann dazu führen, dass es nicht mehr reagiert. In diesem Thema erfahren Sie mehr über C#-Speicherlecks.

Es liegt in der Verantwortung eines Garbage Collectors, den nicht verwendeten zugewiesenen Speicher freizugeben, aber wir stoßen immer noch auf das Problem eines Speicherverlusts, da wir manchmal auf das nicht verwendete Objekt von einer Variablen verweisen, die während der gesamten Lebensdauer der Anwendung nie den Gültigkeitsbereich verlässt.

Syntax

Es gibt viele Möglichkeiten, Speicherverluste in C# zu vermeiden; Mithilfe der „using“-Anweisung, die intern die Dispose()-Methode aufruft, können wir Speicherverluste beim Arbeiten mit nicht verwalteten Ressourcen vermeiden. Die Syntax für die „using“-Anweisung lautet wie folgt:

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

In den obigen Anweisungen ist „var“ das Schlüsselwort, das zum Speichern beliebiger Datentypen verwendet wird, und der Compiler kann diesen Datentyp zum Zeitpunkt der Kompilierung ermitteln. „objectName“ ist ein beliebiger benutzerdefinierter Name für das Objekt. „new“ ist das Schlüsselwort, das zum Initialisieren des Objekts verwendet wird, und „AnyDisposableType“ kann jede Klasse wie StreamReader, BinaryReader, SqlConnection usw. sein, deren Objekt mit Hilfe der „using“-Anweisung entsorgt werden kann.

Wie funktioniert Memory Leak in C#?

Für .NET-Anwendungen verfügen wir über einen Garbage Collector, der den ungenutzten Speicher entsorgt, aber dennoch stoßen wir auf das Problem von Speicherlecks. Das bedeutet nicht, dass der Garbage Collector nicht richtig funktioniert, aber das liegt an einer gewissen Unwissenheit des Programmierers.

Angenommen, wir ignorieren Speicherlecks in unserer Anwendung über einen sehr langen Zeitraum. In diesem Fall erhöhen wir den Speicherverbrauch unserer Anwendung, was die Leistung unserer Anwendung beeinträchtigt und sie nach und nach zerstören kann, was zur OutOfMemoryException führt.

Es gibt zwei Hauptursachen für Speicherverluste in C#:

  • Die erste Ursache ist ein ungenutztes Objekt, das nicht mehr benötigt wird, aber dennoch von einer Variablen referenziert wird, deren Gültigkeitsbereich während der gesamten Lebensdauer der Anwendung gültig ist. Da dieses Objekt über eine Referenz verfügt, wird es vom Garbage Collector nicht zerstört, bleibt für immer im Speicher und kann ein Grund für einen Speicherverlust sein. Ein Beispiel für diese Situation kann eine Veranstaltung sein, die wir zwar angemeldet, aber nie wieder abgemeldet haben.
  • Die zweite Ursache ist die Zuweisung des Speichers für nicht verwaltete Ressourcen und die anschließende Nichtfreigabe nach der Verwendung. Wie verwaltete Ressourcen können nicht verwaltete Ressourcen nicht automatisch durch Müll gesammelt werden. Daher liegt es in der Verantwortung des Programmierers, diesen Speicher nach der Verwendung freizugeben.

Einige Gründe, die zu einem Speicherverlust in C# führen, sind folgende:

  • Wenn wir ein Ereignis abonnieren, enthält die Klasse, die das Ereignis veröffentlicht, einen Verweis auf die Klasse, die es abonniert. Aus diesem Grund entsorgt der Garbage Collector das Objekt der Klasse, die das Ereignis abonniert hat, nicht. Wenn der Programmierer dieses Ereignis nicht abbestellt, führt dies gleichzeitig zu einem Speicherverlust.
  • Das Erfassen eines Klassenmitglieds mit einer anonymen Methode kann zu einem Speicherverlust führen.
  • Statische Klassen und ihre zugehörigen statischen Variablen sowie alles, was von diesen statischen Variablen referenziert wird, können niemals durch Garbage Collection erfasst werden und können zu einem Speicherverlust führen.
  • Die Verwendung der Caching-Funktionalität über einen unbestimmten Zeitraum kann zu einem Speicherverlust führen.
  • Wenn wir einen unendlich laufenden Thread haben, der in unserer Anwendung keine Aufgabe, sondern Verweise auf Objekte hat, kann dies zu einem Speicherverlust führen.
  • Der Garbage Collector verwaltet die nicht verwalteten Ressourcen nicht. Daher kann es zu einem Speicherverlust führen, wenn die nicht verwalteten Ressourcen nach der Verwendung nicht entsorgt werden.

Beispiele für C#-Speicherverlust

Verschiedene Beispiele sind unten aufgeführt:

Beispiel #1

Dieses Beispiel zeigt einen Thread, der darauf wartet, dass er beendet wird, und somit zu einem Speicherverlust führen kann.

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();
}
}
}

Ausgabe:

C#-Speicherleck

Immer wenn wir im obigen Programm die Eingabetaste drücken, erhöht sich die Speicherauslastung.

Beispiel #2

Beispiel, das die Verwendung nicht verwalteter Ressourcen mithilfe der „using“-Anweisung zeigt, um einen Speicherverlust zu vermeiden.

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();
}
}
}

Ausgabe:

C#-Speicherleck

C#-Speicherleck

Wie vermeide ich OutOfMemoryException in C#?

Einige Punkte, die Sie beachten sollten, um eine OutOfMemoryException aufgrund eines Speicherverlusts in C# zu vermeiden, sind wie folgt:

  • Wenn wir ein Event abonniert haben, müssen wir den Event-Handler vom Event abmelden. Wir können dies tun, indem wir IDisposable implementieren.
  • Durch das Erfassen der lokalen Variablen anstelle der Klassenvariablen in der anonymen Methode kann ein Speicherverlust vermieden werden.
  • Durch die Vermeidung der übermäßigen Verwendung statischer Variablen in unserer Anwendung, insbesondere wenn es sich bei diesen Variablen um Referenztypen handelt, können wir die Situation eines Speicherverlusts vermeiden.
  • Wenn unsere Anwendung über Caching-Funktionen verfügt, müssen wir den Cache regelmäßig leeren, insbesondere wenn er über einen längeren Zeitraum nicht genutzt wird. Wir können auch die Caching-Größe begrenzen und WeakReference verwenden, um zwischengespeicherte Objekte zu speichern.
  • Die ordnungsgemäße Verwaltung von Threads in Anwendungen vermeidet Speicherlecks.

Fazit

Wenn eine Anwendung den Speicher, den sie während ihrer Ausführung verwendet hat, nicht freigibt, wird dieser Speicher blockiert und kann von keinem anderen Prozess verwendet werden, was zu einem Speicherverlust führt. Der Garbage Collector kann verwaltete Objekte automatisch entsorgen, nicht jedoch nicht verwaltete Objekte oder Ressourcen.

Das obige ist der detaillierte Inhalt vonC#-Speicherleck. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn