Вопросы утечки памяти - PullRequest
       23

Вопросы утечки памяти

2 голосов
/ 03 ноября 2010

Я много читал об этом, так как меня попросили исправить приложение C #, которое имеет проблемы с утечкой памяти, но я не нашел ответа на эти 2 проблемы:

Рассмотримследующий код:

   private static ArrayList list = new ArrayList();

   public void Function()
   {
     list.add(object1);
     list.add(object2);

     //didn't call clear() prior to reusing list
     list = new ArrayList();
   }

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

Вторая проблема связана с Form.Dispose ().Я вижу, что многие элементы управления, доступные в представлении конструктора (например, ярлыки, графические блоки), требуют удаления.Кажется, что вызов Dispose () в форме приводит к тому, что все эти типы элементов управления также удаляются (исправьте меня, если я ошибаюсь), что странно, так как дизайнер добавляет переопределенный void Dispose (удаление bool) метод, который не делает такой вещи.Я предполагаю, что это происходит в методе void Dispose (удаление bool) базового класса Form.

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

Кроме того, если мне нужно добавить код для удаления определенных объектов, то как мне справиться с тем фактом, что дизайнер уже переопределил void Утилизация (утилизация bool) метод?Должен ли я редактировать код, сгенерированный дизайнером, или есть более чистый способ сделать это?

Надеюсь, это не смущало, это немного сложно объяснить.Спасибо

Ответы [ 3 ]

8 голосов
/ 03 ноября 2010

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

Класс Form знает, как располагать себя, а также все элементы управления, которые являются дочерними окнами в этой форме. Это происходит, когда пользователь закрывает форму, сообщение WM_CLOSE, которое отправляет Windows, вызывает этот код. Коллекция Form.Controls помогает найти ссылку на все дочерние элементы управления, поэтому она также может ими распоряжаться.

Однако этого не произойдет, если вы удалите элементы управления из формы самостоятельно. Теперь вам нужно вызвать Dispose () для них. Особенно опасен метод Controls.Clear (). Что необычно в этом, так это то, что это вызывает постоянную утечку, удаляемые элементы управления сохраняются в «окне парковки». Который поддерживает дескриптор окна живым, так что вы можете переместить их в другое место, например, в другое окно контейнера. Если вы на самом деле не перемещаете их, они останутся на этом парковочном окне навсегда. Никакие другие классы в фреймворке так не ведут себя.

Эта утечка легко диагностируется с помощью Taskmgr.exe, вкладка Процессы. Просмотр + Выберите столбцы и отметьте объекты USER. Если это неуклонно возрастает во время работы вашей программы, значит, вы теряете элементы управления.

1 голос
/ 04 ноября 2010

Во многих средах управления памятью, собираемых мусором и другим образом, освобождение памяти в приложении, как правило, не приводит к тому, что приложение освобождает эту память, а вместо этого фиксирует тот факт, что память должна быть доступна для будущих запросов.Часть идеи, стоящей за сборкой мусора, заключается в том, что когда пользовательский код запрашивает память и приложение знает, что у него по крайней мере столько же доступной сразу, ни код, ни приложение не будут заботиться о том, «распределена» ли какая-либо память, не необходимая для этого запроса.или "бесплатно".Когда последняя достижимая ссылка на объект уничтожается или становится недоступной, объект фактически сразу же перестает существовать, но, как правило, нет особой цели пытаться восстановить память, ранее использовавшуюся несуществующими объектами, до тех пор, пока такая рекламация не потребуется длявыполнить запрос на выделение, или соотношение «количество освобожденной памяти за время, потраченное на него» настолько велико, насколько вероятно его получить.

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

Слабые ссылки и используемые ссылкидля финализации оба автоматически аннулируются GC, когда все другие ссылки на объект отбрасываются, и, таким образом, не вызывают утечек памяти.Однако есть и другой тип ссылки , который может вызвать неприятные утечки : подписки на события от издателей, которые переживают подписчиков.Если объект A подписывается на событие из объекта B, объект A не может быть собран сборщиком мусора, если либо (1) он не отписывается от события, либо (2) B сам не получает права на сборку мусора.Я озадачен тем, почему Microsoft не включила некоторые средства автоматической отмены подписки на события, но они этого не сделали.

1 голос
/ 03 ноября 2010

Каков объем вашего статического массива. Смотрит мне, что у него есть область видимости. Если это так, он не будет утилизирован, поскольку статические объекты всегда считаются корневыми и имеют время жизни приложения. По моему опыту, статика всегда занимает больше памяти и повышается до 2-го поколения из-за этого факта. Если у вас есть какие-либо сомнения, возьмите профилировщик памяти .net и проверьте его. Вы также можете взять дамп памяти и проанализировать его, используя windbg, чтобы выяснить истинную причину утечки.

...