2010-06-10 16 views
6

Ich möchte den folgenden Code in C# schreiben. a) kleine Konsolenanwendung, die Speicherlecks simuliert. b) kleine Konsole-Anwendung, die die oben genannte Anwendung aufrufen und es sofort lösen würde, Speicherverlustproblem zu managen.C#: simulieren Speicherlecks

Mit anderen Worten würde die (b) Anwendung ständig Anwendung aufrufen und freigeben (a), um zu simulieren, wie die " rebellische "Memory-Leak-Anwendung wird ohne die Ursache, die Anwendung (a) ist Adressierung enthalten.

Einige Beispielcode für Anwendung (a) und (b) wäre sehr hilfreich.

Dank

+2

Das klingt wie Hausaufgaben für mich. –

Antwort

11

Die undichte Anwendung könnte wie folgt aussehen:

public static void Main() 
{ 
    var list = new List<byte[]>(); 
    while (true) 
    { 
    list.Add(new byte[1024]); // Change the size here. 
    Thread.Sleep(100); // Change the wait time here. 
    } 
} 

Und die aufrufende Anwendung könnte wie folgt aussehen:

public static void Main() 
{ 
    Process process = Process.Start("leaker.exe"); 
    process.Kill(); 
} 

einen Blick auf die Klasse properties on the Process nehmen. Es gibt mehrere, die zurückgeben, wie viel Speicher der Prozess verbraucht. Sie können möglicherweise einen von ihnen verwenden, um den Prozess bedingt zu beenden.

+0

Ich habe Ihren Beispielcode implementiert. My Leaker.exe beginnt mit 6 MB Speicherverbrauch pro Task-Manager-Registerkarte. Ich weiß nicht, welche Eigenschaft ich verwenden könnte, um es zu messen ... Ich bekomme mehrere Eigenschaften von NonpagedSystemMemorySize bis hin zu VirtualMemorySize64, aber ich weiß nicht, welche Eigenschaft der Task-Manager-Speicherbelegung entsprechen würde. Ich habe versucht, Speichereigenschaft Werte zu Konsole, aber immer noch kein Glück zu drucken. Bitte helfen Sie. –

+0

Lassen Sie den Speicher den Speicher aggressiver verbrauchen, indem Sie ein größeres Byte-Array erstellen. Versuchen Sie es mit 'PrivateMemorySize64'. Es sollte im Laufe der Zeit schleichen. –

1

Sie können durch einfaches Hinzufügen von Objekten zu einer globalen Liste auf einem Timer ein Speicherleck simulieren.

3

Erstellen Sie einfach IDisposable Objekte und entsorgen Sie sie nicht! wobei Beispiele ImageGraphics oder irgendeine Art von Griff oder Code, der verzweigt sich in nicht verwalteten Code aus erstellen/verwalten Ressourcen.

+1

IDisposable macht hier nichts besonderes. Jedes Objekt funktioniert, solange Sie es nicht unerreichbar machen. – Joey

0

Die unten genannten Adressen, was Sie wollen in (a) ein allmähliches Speicherleck von einer Konsole App, wo Sie die Menge an Leck und die Dauer, um es zu leak.

  1. Console App, die allmählich frißt Speicher
  2. Parameter # 1 ist der Speicher it Up in Megabytes Essen wird (dh 6000 ist 6 Gigs)
  3. Parameter # 2 ist die allmähliche Verzögerung für jede Iteration (dh 1000 ist 1 Sekunde)
  4. die Committed Speicher und Arbeitsseiten rund um die Same
  5. sein

Es wurde entwickelt, um verwenden XmlNode als das Objekt, das Speicher in Anspruch nimmt, weil dann die zugesicherten Speicher (Speicher durch den Prozess in OS zugewiesen) und WORKING SET MEMORY (Speicher tatsächlich durch das Verfahren verwendet wird) die gleiche sein würde. Wenn ein primativer Typ verwendet wird, um Speicher wie ein Array byte [] aufzunehmen, dann ist das WORKING SET normalerweise nichts, weil der Speicher tatsächlich nicht vom Prozess verwendet wird, obwohl er zugewiesen wurde.

Stellen Sie sicher, in x64 unter den Projekteigenschaften in der Registerkarte Erstellen zu kompilieren. Andernfalls, wenn es in x32 kompiliert wird, wird es einen OutOfMemory-Fehler um das 1.7Gigs-Limit erhalten. In x64 wird der Speicher, den er verschlingt, ziemlich "grenzenlos" sein.

using System; 
using System.Xml; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading; 
using System.Threading.Tasks; 
using System.Runtime.InteropServices; 

namespace MemoryHog 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Console.WriteLine(" Total Memory To Eat Up in Megs: " + args[0]); 
      Console.WriteLine("Millisecs Pause Between Increments: " + args[1]);    
      int memoryTotalInMegaBytes  = Convert.ToInt32(args[0]); 
      int secondsToPause    = Convert.ToInt32(args[1]); 

      Console.WriteLine("Memory Usage:" +  Convert.ToString(GC.GetTotalMemory(false))); 

      long runningTotal = GC.GetTotalMemory(false); 
      long endingMemoryLimit = Convert.ToInt64(memoryTotalInMegaBytes) * 1000 *  1000; 
      List<XmlNode> memList = new List<XmlNode>(); 
      while (runningTotal <= endingMemoryLimit) 
      { 
       XmlDocument doc = new XmlDocument(); 
       for (int i=0; i < 1000000; i++) 
       { 
        XmlNode x = doc.CreateNode(XmlNodeType.Element, "hello", ""); 
        memList.Add(x); 
       } 
       runningTotal = GC.GetTotalMemory(false); 
       Console.WriteLine("Memory Usage:" +  Convert.ToString(GC.GetTotalMemory(false))); 
       Thread.Sleep(secondsToPause); 
      } 
      Console.ReadLine(); 

     } 

    } 
} 

Und als Brian Gideons Antwort bereits empfohlen, können Sie diese aufrufen, indem Sie den folgenden Code verwenden und tötet dann den Prozess Ihrerseits (b).Das folgende Beispiel ruft MemoryHog.exe (das Programm aus dem Code oben) 6 Gigs zu essen und eine Pause alle 2 Sekunden

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Diagnostics; 
using System.Threading.Tasks; 

namespace ProcessLauncher 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Process process = Process.Start("MemoryHog.exe", "6000 2000"); 
      Console.Read(); 
      process.Kill(); 

     } 
    } 
} 
0

Ich habe meine mit diesem Code:

internal class Program 
{ 
    private static void Main(string[] args) 
    { 
     try 
     { 
      var limit = 9400; 
      while (true) 
      { 
       var thread = new Thread(() => IncreaseMemory(limit)); 
       thread.Start(); 
      } 
     } 
     catch (Exception) 
     { 
      // swallow exception 
     } 

    } 

    private static void IncreaseMemory(long limity) 
    { 
     var limit = limity; 

     var list = new List<byte[]>(); 
     try 
     { 
      while(true) 
      { 
       list.Add(new byte[limit]); // Change the size here. 
       Thread.Sleep(1000); // Change the wait time here. 
      } 
     } 

     catch (Exception ex) 
     { 
      // do nothing 
     } 
    } 

} 
0

Ich habe versuchte, den Ansatz zu verwenden, der in der angenommenen Antwort beschrieben wird, aber es hat nicht funktioniert - es sieht so aus, als ob Compiler oder Laufzeit dies optimiert hätten.

Ich habe die einfachste Modifikation gefunden, die diese Arbeit macht:

var rnd = new Random(); 
var list = new List<byte[]>(); 
while (true) 
{ 
    byte[] b = new byte[1024]; 
    b[rnd.Next(0, b.Length)] = byte.MaxValue; 
    list.Add(b); 

    Thread.Sleep(10); 
} 

Dieser Code macht die Anwendung verbrauchen mehr und mehr Speicher.