Не будет игнорировать утечки памяти IDisposable?

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

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

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

Ответ 1

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

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

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

Ответ 2

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

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

Ответ 3

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

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

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

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

Ответ 4

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

Ответ 5

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

Ответ 6

Большая проблема заключается в том, когда GC работает.

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

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, а в событии load формы просто создайте новый GcTest

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

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

Ответ 7

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