繁体   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