簡體   English   中英

c#:模擬內存泄漏

[英]c# : simulate memory leaks

我想在c#中編寫以下代碼。 a)模擬內存泄漏的小型控制台應用程序。 b)小型控制台應用程序,它將調用上述應用程序並立即釋放它,模擬管理內存泄漏問題。

換句話說,(b)應用程序將連續調用和釋放應用程序(a)以模擬“反叛”內存泄漏應用程序如何被包含而不解決應用程序(a)的根本原因。

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

謝謝

泄漏的應用程序可能如下所示:

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

看一下Process類的屬性 有幾個返回進程消耗的內存量。 您可以使用其中一個來有條件地終止該過程。

只需創建IDisposable對象,不要丟棄它們! 示例是Image Graphics或任何類型的句柄或代碼,它們分支到非托管代碼中以創建/管理資源。

以下內容解決了您想要的問題(a)從控制台應用程序中逐漸記憶泄漏,您可以在其中設置泄漏量和泄漏時間。

  1. 逐漸耗盡內存的控制台應用程序
  2. 參數#1是它將以兆字節消耗的內存(即6000是6 Gigs)
  3. 參數#2是每次迭代的漸變延遲(即1000是1秒)
  4. 承諾的記憶和工作集將圍繞相同

它被設計為使用XmlNode作為占用內存的對象,因為COMMITTED MEMORY(由OS中的進程分配的內存)和WORKING SET MEMORY(進程實際使用的內存)將是相同的。 如果使用原始類型來占用諸如byte []數組之類的內存,則WORKING SET通常什么都不是,因為即使已經分配了內存,該進程實際上也不會使用該內存。

確保在Build選項卡下的Project Properties下的x64中編譯。 否則,如果它在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();

        }

    }
}

正如Brian Gideon的答案已經建議的那樣,您可以使用以下代碼調用此函數,然后將您的部分(b)刪除。 下面的示例調用MemoryHog.exe(上面代碼中的程序)占用6 Gigs並且每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();

        }
    }
}

在控制台或Win應用程序中創建一個Panel對象(panel1),然后添加1000 PictureBox並設置其Image屬性,然后調用panel1.Controls.Clear 所有PictureBox控件仍然在內存中, GC無法收集它們:

var panel1 = new Panel();
var image = Image.FromFile("image/heavy.png");
for(var i = 0; i < 1000;++i){
  panel1.Controls.Add(new PictureBox(){Image = image});
}
panel1.Controls.Clear(); // => Memory Leak!

這樣做的正確方法是

for (int i = panel1.Controls.Count-1; i >= 0; --i)
   panel1.Controls[i].Dispose();

調用Controls.Clear()時內存泄漏

調用Clear方法不會從內存中刪除控制句柄。 您必須顯式調用Dispose方法以避免內存泄漏

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

我用這段代碼創建了我的:

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

}

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

我找到了最簡單的修改,使其工作:

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

此代碼使應用程序消耗越來越多的內存。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM