Утечка памяти в C # - PullRequest
       104

Утечка памяти в C #

54 голосов
/ 07 марта 2009

Возможно ли когда-либо в управляемой системе утечка памяти, когда вы убедитесь, что все ручки, вещи, которые реализуют IDispose, расположены?

Были бы случаи, когда некоторые переменные не учитывались?

Ответы [ 21 ]

2 голосов
/ 07 марта 2009

Как только все ссылки на объект исчезнут, сборщик мусора освободит этот объект при следующем проходе. Я бы не сказал, что утечка памяти невозможна, но это довольно сложно, для того, чтобы просочиться, вы должны иметь ссылку на объект, сидящий без осознания этого.

Например, если вы создаете экземпляры объектов в списке, а затем забыли удалить их из списка, и не забудьте утилизировать их.

1 голос
/ 07 марта 2009

Возможны утечки, если неуправляемые ресурсы не очищаются должным образом. Классы, которые реализуют IDisposable , могут утекать.

Однако обычные ссылки на объекты не требуют явного управления памятью, как это делают языки более низкого уровня.

1 голос
/ 22 января 2010

Не совсем утечка памяти, но при использовании больших объектов не так просто исчерпать память (больше 64 КБ, если я правильно помню). Они хранятся на LOH, и это НЕ дефрагментировано. Таким образом, использование этих больших объектов и их освобождение освобождает память на LOH, но эта свободная память больше не используется средой выполнения .NET для этого процесса. Таким образом, вы можете легко исчерпать пространство на LOH, используя всего несколько больших объектов на LOH. Эта проблема известна Microsoft, но, насколько я помню, решение для этого планируется.

0 голосов
/ 07 марта 2019

При использовании .NET XmlSerializer может возникнуть утечка памяти, поскольку в нем используется неуправляемый код, который не будет утилизироваться.

См. Документы и поиск "утечки памяти" на этой странице:

https://docs.microsoft.com/en-us/dotnet/api/system.xml.serialization.xmlserializer?view=netframework-4.7.2

0 голосов
/ 28 ноября 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, чтобы избежать утечек памяти

0 голосов
/ 13 декабря 2017

напоминание о себе Как найти утечку памяти:

  • Удалить и gc.collect звонки.
  • Подождите, пока мы не убедимся, что память просачивается.
  • Создание файла дампа из диспетчера задач.
  • Откройте файлы дампа, используя DebugDiag .
  • Сначала проанализируйте результат. Результат оттуда должен помочь нам, что обычно занимает большую часть памяти.
  • Исправляйте код до тех пор, пока в нем не будет обнаружена утечка памяти.
  • Используйте сторонние приложения, такие как .net profiler. (Мы можем использовать пробную версию, но нужно решить проблему как можно скорее. Первый дамп должен помочь нам в основном о том, как протекает)
  • Если проблема в виртуальной памяти, нужно следить за неуправляемой памятью. (Обычно там есть другая конфигурация, которую нужно включить)
  • Запустите стороннее приложение в зависимости от того, как оно используется.

Общая проблема с утечкой памяти:

  • События / делегаты никогда не удаляются. (При утилизации убедитесь, что событие не зарегистрировано) - см. ReepChopsey ответ
  • Список / Словарь никогда не очищались.
  • Объект, на который ссылается другой объект, сохраненный в памяти, никогда не будет уничтожен. (Клонируйте его для более легкого управления)
0 голосов
/ 15 июля 2017

Небольшие функции помогают избежать «утечек памяти». Потому что сборщик мусора освобождает локальные переменные в конце функций. Если функция большая и занимает много памяти, вам нужно освободить локальные переменные, которые занимают много памяти и больше не нужны. Аналогичные глобальные переменные (массивы, списки) также плохие.

У меня возникли утечки памяти в C # при создании изображений, а не при их утилизации. Что немного странно. Люди говорят, что вы должны вызывать .Dispose () для каждого объекта, который имеет его. Но документация для графических функций C # не всегда упоминает об этом, например, для функции GetThumbnailImage (). Я думаю, что компилятор C # должен предупредить вас об этом.

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

Если это считается утечкой памяти, этого можно добиться и с помощью такого кода:

public class A
{
    B b;
    public A(B b) { this.b = b; }
    ~A()
    {
        b = new B();
    }
}

public class B
{
    A a;
    public B() { this.a = new A(this); }
    ~B()
    {
        a = new A(this);
    }
}

class Program
{
    static void Main(string[] args)
    {
        {
            B[] toBeLost = new B[100000000];
            foreach (var c in toBeLost)
            {
                toBeLost.ToString(); //to make JIT compiler run the instantiation above
            }
        }
        Console.ReadLine();
    }
}
0 голосов
/ 03 ноября 2009

На моей последней работе мы использовали стороннюю библиотеку .NET SQLite, которая просочилась как сито.

Мы делали много быстрых вставок данных в странной ситуации, когда соединение с базой данных приходилось каждый раз открывать и закрывать. Сторонняя библиотека открывала некоторые из тех же соединений, которые мы должны были делать вручную, и не документировала их. Он также хранил ссылки там, где мы никогда не находили. В результате было открыто в два раза больше соединений, чем предполагалось, и только половина была закрыта. И поскольку ссылки были сохранены, у нас произошла утечка памяти.

Это, очевидно, не то же самое, что классическая утечка памяти в C / C ++, но, по сути, она была для нас одной.

0 голосов
/ 07 марта 2009

Хотя возможно, что что-то в структуре имеет утечку, более вероятно, что у вас есть что-то, что не утилизируется должным образом или что-то блокирует сборщик мусора от его утилизации, IIS будет основным кандидатом для этого ,

Просто помните, что не все в .NET является полностью управляемым кодом, COM-взаимодействием, файлами, такими как потоки файлов, запросы БД, изображения и т. Д.

Проблема, с которой мы столкнулись некоторое время назад (.net 2.0 на IIS 6), заключалась в том, что мы создали бы изображение, а затем избавились от него, но IIS некоторое время не освобождала память.

...