Возможны ли утечки памяти в управляемых средах, таких как .NET? - PullRequest
8 голосов
/ 15 апреля 2011

В C ++ легко иметь постоянную утечку памяти - просто выделите память и не освобождайте ее:

new char; //permanent memory leak guaranteed

, и эта память остается выделенной на время жизни кучи (как правило, то же самое)как продолжительность выполнения программы).

То же самое (случай, который приведет к тому, что конкретный объект, на который нет ссылок, никогда не будет освобожден, пока механизмы управления памятью работают должным образом), возможен в программе на C #?

Iвнимательно прочитал этот вопрос и ответы на него, и в нем упоминаются некоторые случаи, которые приводят к более высокому потреблению памяти, чем ожидалось, или IMO, скорее экстремальные случаи, такие как блокировка потока финализатора, но может ли образоваться постоянная утечка вC # программа с нормально работающим управлением памятью?

Ответы [ 7 ]

25 голосов
/ 15 апреля 2011

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

Подобные утечки практически невозможно создать в .NET (если только вы не вызовете неуправляемый код или если во время выполнения не будет ошибки).

Однако вы можете получить еще одну «более слабую» форму утечек: когда ссылка на память существует (так что все еще можно найти и сбросить ссылку, позволяя ГХ освободить память обычно), но вы думали, что этого не произошло, поэтому вы предполагали, объект, на который ссылаются, получат GC'ed. Это может легко привести к неограниченному росту потребления памяти, поскольку вы накапливаете ссылки на объекты, которые больше не используются, но которые не могут быть собраны сборщиком мусора, поскольку на них все еще есть ссылки в вашем приложении.

Итак, то, что обычно считается утечкой памяти в .NET, - это просто ситуация, когда вы забыли , что у вас есть ссылка на объект (например, потому что вы не смогли отписаться от события). Но ссылка существует, и если вы помните об этом, вы можете очистить ее, и утечка исчезнет.

2 голосов
/ 15 апреля 2011

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

1 голос
/ 15 апреля 2011

GC обычно задерживает сбор недоступной памяти на более поздний срок, когда анализ ссылок показывает, что память недоступна. (В некоторых ограниченных случаях компилятор может помочь сборщику мусора и предупредить его о недоступности зоны памяти, когда она станет таковой.)

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

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

1 голос
/ 15 апреля 2011

Это не совсем утечка памяти, но если вы общаетесь с драйверами оборудования напрямую (т.е. не через правильно написанное расширение набора драйверов .net), то вполне возможно перевести оборудование в состояние, гдехотя в вашем коде может быть или не быть фактической утечки памяти, вы больше не можете получить доступ к оборудованию без перезагрузки или ПК ...

Не уверен, что это полезный ответ на ваш вопрос, ноЯ чувствовал, что стоит упомянуть.

0 голосов
/ 15 апреля 2011

Самая простая утечка памяти:

public static class StaticStuff
{
    public static event Action SomeStaticEvent;
}

public class Listener
{
   public Listener() {
      StaticStuff.SomeStaticEvent+=DoSomething;
   }
   void DoSomething() {}
}

экземпляры Listener никогда не будут собраны.

0 голосов
/ 15 апреля 2011

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

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

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

0 голосов
/ 15 апреля 2011

Если мы определяем утечку памяти как условие, при котором память, которая может использоваться для создания объектов, не может использоваться, или память, которая может быть освобождена, не делает

Утечки памяти могут произойти в:

  • События в WPF, где необходимо использовать слабые события. Это особенно может произойти в Прикрепленные свойства .
  • Большие объекты

Фрагментация кучи больших объектов

http://msdn.microsoft.com/en-us/magazine/cc534993.aspx

...