2010-06-10 123 views
6

我想在c#中編寫下面的代碼。 a)模擬內存泄漏的小型控制檯應用程序。 (b)應用程序將不斷地調用和釋放應用程序(a)來模擬如何將「應用程序」(a)模擬爲「叛逆「的內存泄露應用程序正被包含在內,以解決應用程序(a)的根本原因。c#:模擬內存泄漏

應用程序(a)和(b)的一些示例代碼將非常有幫助。

感謝

+2

這聽起來像是我的功課。 – 2010-06-10 23:26:35

回答

11

泄漏的應用程序可能看起來像:

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

,並且調用應用程序可能看起來像:

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

看看在properties on the Process類。有幾個返回進程正在消耗多少內存。您可能能夠使用其中之一來有條件地終止進程。

+0

我實現了你的示例代碼。我的Leaker.exe從每個任務管理器進程選項卡啓動6MB內存使用。我不知道我可以使用哪個屬性來衡量它......我從NonpagedSystemMemorySize一直到VirtualMemorySize64的任何位置都獲得了幾個屬性,但我不知道哪個屬性對應於任務管理器的內存使用情況。我試圖打印內存屬性值來控制,但仍然沒有運氣。請幫忙。 – 2010-06-11 22:55:48

+0

通過創建一個更大的'byte'數組,可以讓leaker更積極地消耗內存。嘗試使用'PrivateMemorySize64'。它應該會隨着時間的推移而逐漸上升。 – 2010-06-12 01:49:37

1

您可以通過簡單地將對象添加到全局列表中的計時器模擬內存泄漏。

3

只需創建IDisposable對象並且不要處理它們!示例是ImageGraphics或分支到非託管代碼以創建/管理資源的任何類型的句柄或代碼。

+1

IDisposable在這裏沒有做任何特別的事情。任何物體都可以工作,只要你不讓它變得無法到達。 – Joey 2010-06-10 23:41:41

0

以下內容解決了(a)控制檯應用程序中的漸進式內存泄漏,您可以在其中設置泄漏量和泄漏持續時間。

  1. 控制檯應用程序逐漸吃掉存儲器
  2. 參數#1是將吃起來以兆字節(即6000是6場演出)
  3. 參數#2是用於每次迭代漸進延時用存儲器(即1000是1秒)
  4. 承諾存儲器和工作集將是大約在同一

它被設計爲使用XmlNode作爲佔用內存的對象,因爲那麼COMMITTED MEMORY(由OS中的進程分配的內存)和WORKING SET MEMORY(進程實際使用的內存)將是相同的。如果使用主數據類型來佔用內存,如byte []數組,那麼WORKING SET通常不算什麼,因爲儘管分配了內存,但內存實際上並未被進程使用。

確保在x64下的Build選項下的Project Properties下編譯。否則,如果它在x32中編譯,那麼它將在1.7Gigs限制附近得到一個OutOfMemory錯誤。在x64中,它消耗的內存將非常「無限」。

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

     } 

    } 
} 

正如布萊恩基甸的答案已經建議,您可以通過使用下面的代碼,然後殺死進程的一部分調用這個(B)。下面的示例調用MemoryHog.exe(從上面的代碼中的程序),吃起來6場演出和暫停每2秒

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

我創建礦與此代碼:

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

我有試圖使用接受的答案中描述的方法,但它不起作用 - 它看起來像編譯器或運行時已經優化了這一點。

我發現這使得這項工作的最簡單的修改:

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

這段代碼的應用程序消耗越來越多的內存。