.net - утечки - ошибки памяти java




Анатомия «утечки памяти» (10)

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

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

StreamReader sr;
using(sr = new StreamReader("somefile.txt"))
{
    //do some stuff
}

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

В перспективе .NET:

  • Что такое утечка памяти ?
  • Как вы можете определить, протекает ли ваше приложение? Каковы эффекты?
  • Как вы можете предотвратить утечку памяти?
  • Если у вашего приложения есть утечка памяти, оно исчезнет, ​​когда процесс завершится или будет убит? Или утечки памяти в вашем приложении влияют на другие процессы в системе даже после завершения процесса?
  • А как насчет неуправляемого кода, доступ к которому осуществляется через COM Interop и / или P / Invoke?

Все утечки памяти устраняются завершением программы.

Утечка достаточного объема памяти, и операционная система может решить проблему от вашего имени.


Использование программы CLR Profiler от Microsoft на создание этих объектов, а также мониторинг, какие объекты живут где-то в куче (фрагментация, LOH и т. д.).


Лучшее объяснение того, как работает сборщик мусора, - в книге Джеффа Рихтерса через C # book (гл. 20). Чтение этого дает большую основу для понимания того, как объекты сохраняются.

Одной из наиболее распространенных причин случайного укоренения объектов является соединение событий вне класса. Если вы подключите внешнее событие

например

SomeExternalClass.Changed += new EventHandler(HandleIt);

и не забудьте отсоединить его, когда вы утилизируете, тогда SomeExternalClass имеет ссылку на ваш класс.

Как упоминалось выше, memprofiler отлично показывает корни объектов, которые, как вы подозреваете, протекают.

Но есть также очень быстрый способ проверить определенный тип - просто использовать WnDBG (вы можете даже использовать это в окне немедленного доступа VS.NET, когда присоединено):

.loadby sos mscorwks
!dumpheap -stat -type <TypeName>

Теперь сделайте то, что, по вашему мнению, удалит объекты этого типа (например, закройте окно). Здесь удобно иметь кнопку отладки, которая будет запускать System.GC.Collect() пару раз.

Затем !dumpheap -stat -type <TypeName> запустите !dumpheap -stat -type <TypeName> . Если число не уменьшилось или не снизилось так сильно, как вы ожидаете, у вас есть основания для дальнейшего расследования. (Я получил этот совет от семинара, проведенного Инго Раммером ).


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

Для получения дополнительной информации, пожалуйста, посетите http://all-about-java-and-weblogic-server.blogspot.in/2014/01/what-is-memory-leak-in-java.html .


Почему люди думают, что утечка памяти в .NET отличается от любой другой утечки?

Утечка памяти - это когда вы подключаетесь к ресурсу и не отпускаете его. Вы можете сделать это как в управляемом, так и в неуправляемом кодировании.

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

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

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

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

В управляемых терминах я поставлю свою шею на линии, чтобы сказать, что она исчезнет, ​​как только процесс будет убит / удален.

Я вижу, что многие люди имеют это, и я действительно надеюсь, что это закончится. Вы не можете попросить пользователя закрыть ваше приложение, чтобы навести порядок! Посмотрите на браузер, который может быть IE, FF и т. Д., Затем откройте, скажем, Google Reader, оставьте его на несколько дней и посмотрите, что произойдет.

Если затем вы откроете другую вкладку в браузере, зайдете на какой-нибудь сайт, а затем закроете вкладку, на которой размещена другая страница, из-за которой произошла утечка браузера, вы думаете, браузер освободит память? Не так с IE. На моем компьютере IE легко съест 1 ГБ памяти за короткий промежуток времени (около 3-4 дней), если я использую Google Reader. Некоторые газеты еще хуже.


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

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

Что касается освобождения памяти при завершении процесса, если только вы не используете Win98 или ее эквивалент, все возвращается к ОС после завершения. Единственными исключениями являются вещи, которые открываются кросс-процессами, а у другого процесса ресурс остается открытым.

COM-объекты могут быть сложными, хотя. Если вы всегда используете шаблон IDispose , вы будете в безопасности. Но я столкнулся с несколькими сборками взаимодействия, которые реализуют IDispose . Ключевым моментом здесь является вызов Marshal.ReleaseCOMObject когда вы закончите с ним. COM-объекты все еще используют стандартный подсчет ссылок COM.


Я бы определил утечки памяти как объект, не освобождающий всю память, выделенную после ее завершения. Я обнаружил, что это может произойти в вашем приложении, если вы используете Windows API и COM (т. Е. Неуправляемый код, в котором есть ошибка или неправильно управляется), в среде и в сторонних компонентах. Я также обнаружил, что проблема может быть в том, чтобы не убирать после использования определенных предметов, таких как ручки.

Я лично перенес исключения из памяти, которые могут быть вызваны, но не исключают утечки памяти в приложениях dot net. (OOM также может прийти от пиннинга, см. Pinning Artical ). Если вы не получаете ошибок OOM или вам необходимо подтвердить, является ли утечка памяти причиной ее возникновения, то единственный способ - профилировать ваше приложение.

Я также попытался бы обеспечить следующее:

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

б) Все, что имеет метод close, снова закрывается с помощью оператора finally или оператора using (хотя я обнаружил, что использование метода не всегда закрывается в зависимости от того, объявлен ли объект вне оператора using)

c) Если вы используете неуправляемый код / ​​Windows API, то после этого они будут корректно обработаны. (у некоторых есть методы очистки для освобождения ресурсов)

Надеюсь это поможет.


Я обнаружил, что memprofiler очень помогает при обнаружении утечек памяти в .Net. Он не бесплатный, как Microsoft CLR Profiler, но, на мой взгляд, более быстрый и точный.


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





com-interop