Каковы способы устранения утечек памяти в C#
Я изучаю C#. Из того, что я знаю, вы должны правильно настроить, чтобы сборщик мусора действительно удалил все, как должно быть. Я ищу мудрость, которой ты научился за эти годы, умный.
Я исхожу из фона C++ и очень привык к запахам кода и шаблонам разработки. Я хочу узнать, как пахнет код в C#. Дай мне совет!
каковы наилучшие способы удаления?
Как вы можете выяснить, когда у вас есть "утечки памяти"?
Edit: я пытаюсь разработать пунш-список "вещей, которые всегда нужно делать для управления памятью"
большое спасибо.
10 ответов
C#, .NET Framework использует управляемую память, и все (но выделенные неуправляемые ресурсы) - это собранный мусор.
можно с уверенностью предположить, что управляемые типы всегда собирали мусор. Это включает arrays
, classes
и structures
. Не стесняйтесь делать int[] stuff = new int[32];
и забыть об этом.
при открытии файла, подключения к базе данных или любого другого неуправляемого ресурса в классе реализуйте интерфейс IDisposable и в методе Dispose отмените выделение неуправляемого ресурс.
любой класс, который реализует IDisposable, должен быть явно закрыт или использоваться в (Я думаю, круто), используя блок like;
using (StreamReader reader = new StreamReader("myfile.txt"))
{
... your code here
}
здесь .NET будет утилизировать читателя, когда из области {}.
первое, что с GC-это то, что он недетерминирован; если вы хотите, чтобы ресурс был быстро очищен, реализуйте IDisposable
и использовать using
; это не собирает управляемую память, но может много помочь с неуправляемыми ресурсами и последующими цепочками.
в частности, вещи, чтобы следить за:
- много закрепления (устанавливает много ограничений на то, что может сделать GC)
- много финализаторов (обычно они вам не нужны; замедляется GC)
- статические события-простой способ сохранить много больших графов объектов в живых ; - p
- события на недорогом объекте длинной жизни, который может видеть дорогой объект, который должен был быть очищен
- "захваченные переменные" случайно сохраняя графики живыми
для исследования утечек памяти... "SOS" - один из самых простых маршрутов; вы можете использовать SOS, чтобы найти все экземпляры типа, и что может его видеть, и т. д.
В общем, чем меньше вы беспокоитесь о распределении памяти в c#, тем лучше. Я бы оставил это профайлеру, чтобы сказать мне, когда у меня возникают проблемы с коллекцией.
вы не можете создавать утечки памяти в C# так же, как в C++. Сборщик мусора всегда будет "иметь вашу спину". Вы можете создавать объекты и хранить ссылки на них, даже если вы никогда их не используете. Это запах код искать.
другое, чем что:
- имейте некоторое представление о том, как часто будет происходить сбор (по соображениям производительности)
- не держите ссылки на объекты дольше, чем вам нужно
- утилизируйте объекты, которые реализуют IDisposable, как только вы закончите с ними (используйте
using
синтаксис) - правильно использовать тег интерфейс IDisposable интерфейс
основными источниками утечек памяти, о которых я могу думать, являются:
сохранение ссылок на объекты, которые вам больше не нужны (обычно в какой-то коллекции), поэтому здесь вам нужно помнить, что все, что вы добавляете в коллекцию, на которую у вас есть ссылка, тоже останется в памяти.
с круговыми ссылками, например, с делегатами, зарегистрированными в событии. Поэтому, даже если вы явно не ссылаетесь на объект, он не может получить мусор собираться, так как один из его методов, зарегистрирован как делегат с событием. В этих случаях необходимо не забыть удалить делегат перед отбрасыванием ссылки.
- взаимодействие с собственным кодом и невозможность его освобождения. Даже если вы используете управляемые оболочки, реализующие завершители, CLR часто не очищает их достаточно быстро, потому что не понимает объем памяти. Вы должны использовать шаблон using(IDisposable) {}
еще одна вещь, которую следует учитывать для управления памятью, - это если вы реализуете какие-либо шаблоны наблюдателей и неправильно удаляете ссылки.
например: Объект Часы Объект Б Объект Б удаляется, если ссылка от A до B, не распорядились собственность ГК не properyly Dispose объекта. Поскольку обработчику событий все еще назначается GC, он не видит его как неиспользуемый ресурс.
Если у вас есть небольшой набор объектов, вы работа с этим может меня не касаться. Однако, если вы работаете с тысячами объектов, это может привести к постепенному увеличению памяти в течение всего срока службы приложения.
есть некоторые большие программные приложения для управления памятью для мониторинга того, что происходит с кучей вашего приложения. Я нашел большую пользу от использования .NET Memory Profiler.
HTH
Я рекомендую использовать .NET профилировщик памяти
.NET Memory Profiler-это мощный инструмент для поиска утечек памяти и оптимизации использования памяти в программах, написанных на C#, VB.NET или любой другой язык .NET.
.NET Memory Profiler поможет вам:
- просмотр в режиме реального времени памяти и информации о ресурсах
- легко определить утечки памяти, собирая и сравнивая снимки .NET память!--12-->
- найти экземпляры, которые не утилизируются
- получить подробную информацию об использовании неуправляемых ресурсов
- оптимизация использования памяти
- исследовать проблемы с памятью в производственном коде
- выполнить автоматическое тестирование памяти
- получить информацию о родной
взгляните на их видео учебники:
другие уже упоминали о важности IDisposable, и некоторые из вещей, чтобы следить за в вашем коде.
Я хотел предложить некоторые дополнительные ресурсы; я нашел следующее бесценным при изучении деталей .NET GC и как устранить проблемы с памятью в приложениях .NET.
CLR через C# Джеффри Рихтер является отлично книги. Стоит цена покупки только для главы о GC и память.
этой блог (по Microsoft "ASP.NET Escalation Engineer") часто является моим источником для Советов и трюков по использованию WinDbg, SOS и для обнаружения определенных типов утечек памяти. Тесс даже разработала .NET debugging demos / labs, которая проведет вас через общие проблемы с памятью и как их распознавать и решать.
инструменты отладки для Windows (WinDbg, SOS, etc)
вы можете использовать такие инструменты, как профилировщик CLR требуется некоторое время, чтобы научиться правильно его использовать, но в конце концов это бесплатно. (Это помогло мне несколько раз найти утечку памяти)
лучший способ убедиться, что объекты удаляются или в .NET lingo, собранный мусор,-это убедиться, что все корневые ссылки (ссылки, которые могут быть прослежены с помощью методов и объектов до первого метода в стеке вызовов потока) на объект имеют значение null.
GC не может и не будет собирать объект, если есть какие-либо корневые ссылки на него, независимо от того, реализует ли он IDisposable или нет.
циркулярные ссылки не налагают штрафа или возможности утечек памяти, поскольку GC отмечает, какие объекты он посетил в графе объектов. В случае делегатов или eventhandlers может быть распространено забыть удалить ссылку в событии на целевой метод, так что объект, содержащий целевой метод, не может быть собран, если событие коренится.
каковы наилучшие способы удаления вещей?
Примечание: следующее работает только для типов, содержащих неуправляемые ресурсы. Это не помогает с чисто управляемыми типами.
вероятно, лучший метод-реализовать и следовать шаблону IDisposable; и вызвать метод dispose для всех объектов, реализующих его.
оператор "using" - ваш лучший друг. Свободно положенный, он вызовет dispose для вас на объекты, реализующие IDisposable.