Будет ли игнорирование IDisposable причиной утечки памяти? - PullRequest
12 голосов
/ 29 июля 2011

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

Класс, который обрабатывает неуправляемые ресурсы, вероятно, реализует IDisposable. Если игнорировать это и ни вызывать Dispose, ни оборачивать объект в using - не приведет ли это к утечке неуправляемого ресурса? Или это будет должным образом очищено, когда GC собирает объект?

Можно предположить, что класс, обрабатывающий неуправляемый ресурс, имеет правильную реализацию IDisposable, включая финализатор и т. Д.

Ответы [ 7 ]

14 голосов
/ 29 июля 2011

Это не приведет к утечке памяти .Фактически, Dispose не имеет абсолютно никакого отношения к управлению памятью.

Это создаст утечку ресурсов .И хотя ГХ обычно очищает его, это может быть слишком редко и слишком поздно.

Пропуск утилизации (using) может замедлить или даже вызвать сбой вашего приложения.В случае файловых ресурсов или соединений Db это может даже вызвать проблемы в других приложениях.

9 голосов
/ 29 июля 2011

Я не буду вызывать управляемых утечек памяти.Это может вызвать утечки в неуправляемом коде, на который есть ссылки.Но это еще хуже: памяти в современных системах достаточно, чтобы вы могли на некоторое время обойтись с серьезной утечкой.Свидетель Mozilla Firefox: он имел обыкновение (все еще?) Течь как сито, и миллионы были рады его использовать.

Большая проблема - другие ресурсы, которые могут вообще не иметь никакого отношения к памяти.Примеры включают соединения с базой данных, дескрипторы системного ввода-вывода, дескрипторы сокетов, файловые дескрипторы и тому подобное.Это все элементы, в которых вы можете легко создавать ситуации отказа в обслуживании в вашей собственной системе, если вы не будете осторожны с правильным использованием IDisposable.

4 голосов
/ 29 июля 2011

Просто добавить немного к ответам Хенка и Джоэла

То, что вы описали, довольно часто происходит именно с соединениями с БД. Достаточно, чтобы был добавлен счетчик производительности ADO.NET NumberOfReclaimedConnections. Этот счетчик отслеживает ...

Количество соединений, которые были восстановлены через мусор коллекция, в которой Close или Dispose не было вызвано приложением . Неявное закрытие или удаление соединений ухудшает производительность.

Падение производительности обычно длится дольше, чем необходимо, чтобы освободить соединение. Это также может привести к превышению времени ожидания соединения, а не к проблемам с памятью.

2 голосов
/ 29 июля 2011

Если у объекта IDisposable есть финализатор, который освобождает неуправляемую память, то память будет свободна при вызове финализатора (после того, как он помечен для сбора GC и помещен в очередь финализатора), но если естьне является финализатором, и Dispose() никогда не вызывается, тогда память может быть утечка и повторно заявлена ​​только после завершения процесса.

1 голос
/ 29 июля 2011

Большой проблемой является , когда запускает сборщик мусора.

Возьмите следующий класс

class GcTest
{
    private Stopwatch sw = new Stopwatch();
    public GcTest()
    {
        sw.Start();
    }

    ~GcTest()
    {
        sw.Stop();
        Console.WriteLine("GcTest finalized in " + sw.ElapsedMilliseconds + " ms");
    }
}

Установите точку останова на Console.WriteLine, если хотите.

Создайте пустое приложение для форм Windows, и в событии загрузки формы просто создайте новый GcTest

private void Form1_Load(object sender, EventArgs e)
{
    var gcTest = new GcTest();
}

Запустите приложение и дождитесь запуска финализатора.
Скорее всегоон не запустится, пока вы не закроете приложение.

1 голос
/ 29 июля 2011

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

0 голосов
/ 29 июля 2011

Насколько мне известно, сборщик мусора не будет звонить утилизировать.Вы должны назвать это непосредственно или использовать с помощью.Поэтому ответ таков: да, если класс обрабатывает неуправляемые ресурсы, которые освобождаются в Dispose, ваш класс утечет, если вы не вызовите Dispose.

...