Сведения о вопросе

CPdeveloper

09:49, 17th August, 2020

Теги

Утечек памяти .NET

Просмотров: 472   Ответов: 14

Назовите все возможные способы, с помощью которых мы можем получить утечку памяти .NET?

Я знаю о двух из них:

  1. Неправильно не регистрируются обработчики/делегаты событий .
  2. Отказ от использования динамических дочерних элементов управления в формах Windows:

Пример:

// Causes Leaks  
Label label = new Label();  
this.Controls.Add(label);  
this.Controls.Remove(label);  

// Correct Code  
Label label = new Label();  
this.Controls.Add(label);  
this.Controls.Remove(label);  
label.Dispose();

Обновление: идея состоит в том, чтобы перечислить общие подводные камни, которые не слишком очевидны (например, выше). Обычно считается, что утечки памяти не являются большой проблемой из-за сборщика мусора. Не так, как это было раньше в C++.


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

В управляемой среде я бы счел это утечкой памяти, если бы у вас была непреднамеренная ссылка на какой-либо объект, о котором вы не знаете (отсюда два примера в моем вопросе).

Итак, каковы различные возможные способы, которыми может произойти такая утечка памяти?



  Сведения об ответе

LIZA

22:02, 14th August, 2020

Это на самом деле не вызывает утечек, это просто делает больше работы для GC:

// slows GC
Label label = new Label();  
this.Controls.Add(label);  
this.Controls.Remove(label);  

// better  
Label label = new Label();  
this.Controls.Add(label);  
this.Controls.Remove(label);  
label.Dispose();

// best
using( Label label = new Label() )
{ 
    this.Controls.Add(label);  
    this.Controls.Remove(label);  
}

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

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


  Сведения об ответе

JUST___

03:41, 17th August, 2020

Нет никакого способа предоставить исчерпывающий список... это очень похоже на вопрос "How can you get wet?"

Тем не менее, убедитесь, что вы вызываете Dispose() для всего, что реализует IDisposable, и убедитесь, что вы реализуете IDisposable для любых типов, которые потребляют неуправляемые ресурсы любого рода.

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


  Сведения об ответе

FAriza

18:08, 26th August, 2020

Установка свойства GridControl.DataSource непосредственно без использования экземпляра класса BindingSource (http://msdn.microsoft.com/en-us/library/system.windows.forms.bindingsource.aspx ).

Это вызвало утечки в моем приложении, которые заняли у меня довольно много времени, чтобы отследить с помощью профилировщика, в конце концов я нашел этот отчет об ошибке, на который Microsoft ответила: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=92260

Забавно, что в документации для класса BindingSource Microsoft пытается выдать его за хорошо продуманный класс legitmate, но я думаю, что они просто создали его, чтобы решить фундаментальную утечку в отношении валютных менеджеров и привязки данных к элементам управления grid.

Следите за этим, я уверен, что есть абсолютно много дырявых приложений там из-за этого!


  Сведения об ответе

PROGA

23:52, 12th August, 2020

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

Дальнейшее чтение: http://dotnetdebug.net/2005/06/22/blocked-finalizer-thread/


  Сведения об ответе

SEEYOU

10:21, 23rd August, 2020

Исключения в методах finalize (или Dispose-вызовы от завершителя), которые препятствуют правильному размещению неуправляемых ресурсов. Обычно это происходит из-за того, что программист предполагает , какие объекты порядка будут удалены, и пытается освободить одноранговые объекты, которые уже были удалены, что приводит к исключению и rest метода Finalise/Dispose from Finalise не вызывается.


  Сведения об ответе

nYU

04:07, 17th August, 2020

У меня есть 4 дополнительных пункта, чтобы добавить к этому обсуждению:

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

  2. Доступ к неуправляемым ресурсам через Pinvoke и не очистка их может привести к утечке памяти.

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

  4. Создание объектов GDI часто используется для выполнения пользовательского чертежа. При выполнении работы GDI часто, повторное использование одного объекта GDI.


  Сведения об ответе

piter

16:49, 3rd August, 2020

Чтобы предотвратить утечку памяти .NET:

1) используйте конструкцию 'using' (или 'try-finally construct) всякий раз, когда создается объект с интерфейсом 'IDisposable'.

2) Сделайте классы 'IDisposable', если они создают поток или добавляют объект в статическую или долговременную коллекцию. Помните, что C# 'event'-это коллекция.

Вот короткая статья о советах по предотвращению утечек памяти .


  Сведения об ответе

KOMP

09:59, 28th August, 2020

Вы говорите о неожиданном использовании памяти или фактических утечках? Два случая, которые вы перечислили, не являются точными утечками; это случаи, когда объекты задерживаются дольше, чем предполагалось.

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

Edit: или это фактические ошибки в сборщике мусора или неуправляемом коде.

Правка 2: Еще один способ думать об этом-всегда следить за тем, чтобы внешние ссылки на ваши объекты были выпущены соответствующим образом. Внешнее означает код вне вашего контроля. Любой случай, когда это происходит, - это случай, когда вы можете "leak" памяти.


  Сведения об ответе

DINO

06:21, 26th August, 2020

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


  Сведения об ответе

dump

11:03, 25th August, 2020

Тесс Фернандес имеет отличные записи в блоге о поиске и отладке утечек памяти. Лаборатория 6 Лаборатория 7


  Сведения об ответе

PHPH

14:28, 3rd August, 2020

Одна вещь, которая была действительно неожиданной для меня, это:

Region oldClip = graphics.Clip;
using (Region newClip = new Region(...))
{
    graphics.Clip = newClip;
    // draw something
    graphics.Clip = oldClip;
}

Где же утечка памяти? Да, тебе тоже следовало избавиться от oldClip! Потому что Graphics.Clip - это одно из редких свойств, которое возвращает новый одноразовый объект каждый раз, когда вызывается getter.


  Сведения об ответе

PHPH

09:36, 9th August, 2020

  1. Сохранение вокруг ссылок на объекты, которые вам больше не нужны.

Другие комментарии - один из способов обеспечения утилизации попадает под это использовать... когда это позволяет структура кода.


  Сведения об ответе

LAST

23:08, 21st August, 2020

Многие вещи, которые могут вызвать утечку памяти в неуправляемых языках, все еще могут вызвать утечку памяти в управляемых языках. Например, плохие политики кэширования могут привести к утечке памяти.

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


  Сведения об ответе

ЯЯ__4

12:20, 5th August, 2020

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

Тупиковый поток финализатора предотвратит запуск всех оставшихся финализаторов и тем самым предотвратит восстановление всех завершаемых объектов (поскольку они все еще коренятся в списке freachable).

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

Большая куча объектов не уплотняется, поэтому вы можете пропустить память через фрагментацию.

Есть ряд объектов, которые необходимо освободить вручную. E.g. удаленные объекты без аренды и сборок (необходимо выгрузить AppDomain).


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться