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

PASHA

16:03, 1st July, 2020

Теги

Анатомия " утечки памяти"

Просмотров: 638   Ответов: 15

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

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



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

pumpa

18:03, 1st July, 2020

Самое лучшее объяснение ,которое я видел, находится в главе 7 свободной электронной книги Основы программирования.

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

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

Понимание модели памяти .NET - это ваш лучший способ избежать ее. В частности, понимание того, как работает сборщик мусора и как работают ссылки — опять же, я отсылаю вас к главе 7 электронной книги. Кроме того, следует помнить о распространенных ловушках, вероятно, наиболее распространенными из которых являются события. Если объект A зарегистрирован в событии на объекте B, то объект A будет держаться до тех пор, пока объект B не исчезнет, потому что B содержит ссылку на A . Решение состоит в том, чтобы отменить регистрацию событий, когда вы закончите.

Конечно, хороший профиль памяти позволит вам увидеть графики ваших объектов и изучить вложенность / привязку ваших объектов, чтобы увидеть, откуда берутся ссылки и какой корневой объект отвечает ( профиль муравьев red-gate, JetBrains dotMemory , memprofiler -действительно хороший выбор , или вы можете использовать только текстовые WinDbg и SOS, но я настоятельно рекомендую коммерческий/визуальный продукт, если вы не настоящий гуру).

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


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

DAAA

18:03, 1st July, 2020

Строго говоря, утечка памяти потребляет память, которая является "no longer used" программой.

"No longer used" имеет более чем одно значение, это может означать "больше нет ссылок на него", то есть полностью не подлежит восстановлению, или это может означать, что на него ссылаются, его можно восстановить, но программа все равно сохраняет ссылки. Только последнее относится к .Net для идеально управляемых объектов . Однако не все классы совершенны, и в какой-то момент базовая неуправляемая реализация может постоянно утекать ресурсы для этого процесса.

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

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

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


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

pumpa

18:03, 1st July, 2020

Я думаю, что на вопросы "what is a memory leak" и "what are the effects" уже были даны хорошие ответы, но я хотел бы добавить еще несколько вещей по другим вопросам...

Как понять, не утечка ли вашего приложения

Один интересный способ-открыть perfmon и добавить трассировки для # bytes во всех кучах и коллекциях # Gen 2 , в каждом случае глядя только на ваш процесс. Если выполнение определенной функции приводит к увеличению общего количества байтов, и эта память остается выделенной после следующей коллекции Gen 2, можно сказать, что функция пропускает память.

Как предотвратить

Были высказаны и другие хорошие мнения. Я бы просто добавил, что, возможно, наиболее часто упускаемая причина утечек памяти .NET заключается в добавлении обработчиков событий к объектам, не удаляя их. Обработчик событий, прикрепленный к объекту, является формой ссылки на этот объект, поэтому он будет препятствовать сбору данных даже после того, как все другие ссылки будут удалены. Всегда помните об отсоединении обработчиков событий (используя синтаксис -= в C#).

Исчезает ли утечка, когда процесс завершается, и как насчет COM interop?

Когда ваш процесс завершается, вся память, отображенная в его адресное пространство, освобождается OS, включая любые объекты COM, обслуживаемые из DLLs. Сравнительно редко объекты COM могут обслуживаться из отдельных процессов. В этом случае, когда ваш процесс завершается, вы все еще можете нести ответственность за память, выделенную в любых процессах сервера COM, которые вы использовали.


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

LAST

18:03, 1st July, 2020

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

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

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

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

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

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

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


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

SEEYOU

18:03, 1st July, 2020

Если вам нужно диагностировать утечку памяти в .NET, проверьте эти ссылки:

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

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

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

Microsoft также имеет более новый инструмент для помощи в создании аварийных дампов, чтобы заменить ADPlus, называемый DebugDiag.

http://www.microsoft.com/downloads/details.aspx?FamilyID=28bd5941-c458-46f1-b24d-f60151d875a3&displaylang=ru


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

padenie

18:03, 1st July, 2020

Используя CLR профилировщик от Microsoft http://www.microsoft.com/downloads/details.aspx?familyid=86ce6052-d7f4-4aeb-9b7a-94635beebdda&displaylang=en -это отличный способ определить, какие объекты содержат память, какой поток выполнения приводит к созданию этих объектов,а также контролировать, какие объекты живут где на куче (фрагментация, LOH и т. д.).


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

pumpa

18:03, 1st July, 2020

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

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

напр.

SomeExternalClass.Changed += new EventHandler(HandleIt);

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

Как уже упоминалось выше, профилировщик памяти SciTech отлично показывает вам корни объектов, которые вы подозреваете в утечке.

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

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

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

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


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

dump

18:03, 1st July, 2020

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


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

DINO

18:03, 1st July, 2020

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

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

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

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

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

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

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

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

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


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

PIRLO

18:03, 1st July, 2020

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

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

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

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


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

appple

18:03, 1st July, 2020

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

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


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

pumpa

18:03, 1st July, 2020

Я соглашусь с Бернардом относительно того, что в .net году будет утечка мема.

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

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

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


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

DAAA

18:03, 1st July, 2020

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

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

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

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


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

PAGE

18:03, 1st July, 2020

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


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

#hash

18:03, 1st July, 2020

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

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


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

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