c #: симулировать утечки памяти - PullRequest
11 голосов
/ 11 июня 2010

Я хотел бы написать следующий код на c #.а) небольшое консольное приложение, имитирующее утечку памяти.b) небольшое консольное приложение, которое будет вызывать указанное выше приложение и сразу же его выпускать, имитируя проблему управления утечкой памяти.

Другими словами, приложение (b) будет непрерывно вызывать и отпускать приложение (a) для имитации того, как«мятежное» приложение с утечкой памяти сдерживается без устранения основной причины - приложения (a).

Некоторые примеры кода для приложений (a) и (b) были бы очень полезны.

Спасибо

Ответы [ 7 ]

14 голосов
/ 11 июня 2010

Утечка приложения может выглядеть следующим образом:

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 . Есть несколько, которые возвращают, сколько памяти потребляет процесс. Вы можете использовать один из них для условного завершения процесса.

4 голосов
/ 11 июня 2010

Просто создайте IDisposable объекты и не выбрасывайте их!Примерами являются Image Graphics или любой вид дескриптора или кода, который разветвляется в неуправляемый код для создания / управления ресурсами.

3 голосов
/ 06 ноября 2018

В приложении Console или 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, чтобы избежать утечек памяти

3 голосов
/ 19 декабря 2013

Ниже приведено описание того, что вы хотите в (a) постепенной утечке памяти из консольного приложения, где вы можете установить количество утечки и продолжительность утечки.

  1. Консольное приложение, которое постепенно израсходует память
  2. Параметр # 1 - это память, которую он будет съедать в мегабайтах (т.е. 6000 - это 6 гигабайт)
  3. Параметр # 2 - это постепенная задержка для каждой итерации (т. Е. 1000 - 1 секунда)
  4. Фиксированная память и рабочий набор будут примерно одинаковыми

Он был разработан для использования XmlNode в качестве объекта, который занимает память, потому что тогда COMMITTED MEMORY (память, выделенная процессом в ОС) и WORKING SET MEMORY (память, фактически используемая процессом) будут одинаковыми. Если примитивный тип используется для использования памяти, такой как массив byte [], то РАБОЧИЙ НАБОР обычно ничто, потому что память фактически не используется процессом, даже если она была выделена.

Обязательно выполните компиляцию в x64 в разделе «Свойства проекта» на вкладке «Сборка». В противном случае, если он скомпилирован в x32, он получит ошибку OutOfMemory около предела 1.7Gigs. В 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();

        }
    }
}
1 голос
/ 11 июня 2010

Вы можете симулировать утечку памяти, просто добавляя объекты в глобальный список по таймеру.

0 голосов
/ 15 июня 2016

Я попытался использовать подход, описанный в принятом ответе, но он не сработал - похоже, компилятор или среда выполнения оптимизировали это.

Я нашел простейшую модификацию, которая делает эту работу:

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

Этот код заставляет приложение потреблять все больше и больше памяти.

0 голосов
/ 05 февраля 2015

Я создал мой с этим кодом:

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

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...