Почему не can.NET есть утечки памяти?



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



насколько я понимаю, сама структура написана на C++, а C++ восприимчив к утечкам памяти.




  • является ли базовая структура настолько хорошо написана, что она абсолютно не имеет никакой возможности утечки внутренней памяти?

  • есть ли что-то в рамках код, который самостоятельно управляет и даже лечит свои собственные потенциальные утечки памяти?

  • ответ что-то еще, что я не считал?

566   16  

16 ответов:

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


насколько я понимаю, сама структура написана на C++, а C++ восприимчив к утечкам памяти.

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

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

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

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

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

является ли базовая структура настолько хорошо написана, что она абсолютно не имеет никакой возможности утечки внутренней памяти?

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

.NET можете утечка памяти.

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

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

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

после просмотра документации Microsoft, в частности" выявление утечек памяти в среде CLR", Microsoft делает заявление, что до тех пор, пока вы не реализуете небезопасный код в своем приложении, что невозможно иметь утечку памяти

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

из-за сборки мусора у вас не может быть регулярных утечек памяти (кроме особых случаев, таких как небезопасный код и P/Invoke). Однако вы можете, конечно, непреднамеренно сохранить ссылку навсегда, что эффективно утечки памяти.

edit

лучший пример, который я видел до сих пор подлинной утечки обработчик событий += ошибка.

edit

смотрите ниже для объяснения ошибки, и условий, при которых он квалифицируется как подлинная утечка, в отличие от почти подлинной утечки.

вот пример утечки памяти в .NET, которая не связана с unsafe/pinvoke и даже не включает обработчики событий.

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

class Message 
{
  public Message(int id, string text) { MessageId = id; Text = text; }
  public int MessageId { get; private set; }
  public string Text { get; private set; }
}

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

таким образом, вы добавляете новое свойство...

class Message
{
  ...
  public Message PreviousMessage { get; private set; }
  ...
}

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

  Message lastMessageReceived;

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

вот другие утечки памяти, которые этот парень нашел с помощью ANTS .NET Profiler: http://www.simple-talk.com/dotnet/.net-tools/tracing-memory-leaks-in-.net-applications-with-ants-profiler/

Я полагаю, что можно написать программное обеспечение, например, среду выполнения .NET (CLR), которая не пропускает память, если быть достаточно осторожным. Но поскольку Microsoft время от времени выпускает обновления для .NET framework через Центр обновления Windows, я уверен, что там are случайные ошибки даже в среде CLR.

все программное обеспечение может утечка памяти.

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

кроме того, я недавно столкнулся с возможной утечкой памяти в .NET-COM interop настройка. Компоненты COM используют счетчики ссылок, чтобы решить, когда они могут быть освобождены. .NET добавляет еще один подсчет ссылок механизм к этому, на который можно влиять через статический System.Runtime.InteropServices.Marshal класса.

В конце концов, вы все еще должны быть осторожны с управлением ресурсами, даже в программе .NET.

вы можете абсолютно иметь утечки памяти в коде .NET. Некоторые объекты будут, в некоторых случаях, корень себя (хотя они, как правило,IDisposable). Не удается позвонить Dispose() на объекте в этом случае абсолютно вызовет реальную утечку памяти в стиле C/C++ с выделенным объектом, на который у вас нет возможности ссылаться.

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

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

вот пример кода с помощью System.Threading.Timer.

public class Test
{
    static public int Main(string[] args)
    {
        MakeFoo();
        GC.Collect();
        GC.Collect();
        GC.Collect();
        System.Console.ReadKey();
        return 0;
    }

    private static void MakeFoo()
    {
        Leaker l = new Leaker();
    }
}

internal class Leaker
{
    private Timer t;
    public Leaker()
    {
        t = new Timer(callback);
        t.Change(1000, 0);
    }

    private void callback(object state)
    {
        System.Console.WriteLine("Still alive!");
        t.Change(1000, 0);
    }
}

как Гладос на Leaker объект будет бесконечно "все еще жив" - тем не менее, нет никакого способа получить доступ к объекту (кроме внутреннего, и как может объект знает, когда на него больше не ссылаются?)

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

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

но .NET может иметь утечки памяти. утечки GDI распространены среди приложений Windows Forms, например. Один из приложений, которые я помогал развивать опыт это на регулярной основе. И когда сотрудники в офисе используют несколько экземпляров этого в течение всего дня, это не редкость для них, чтобы попасть в 10 000 Ограничение объекта GDI, присущее Windows.

один из основных источников утечки памяти C/C++, что эффективно не существует в .Net, когда нужно освободить общую память

ниже приведен класс Brad Abrams led для проектирования библиотек классов .NET

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

эта ссылка показывает, как утечки могут произойти в .Net с использованием слабых шаблонов событий. http://msdn.microsoft.com/en-us/library/aa970850.aspx

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

книга Джеффри Рихтера CLR через C# есть хорошая глава о том, как память управляется в. NET.

лучший пример, который я нашел, был на самом деле из Java, но тот же принцип применяется к C#.

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

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

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

Edit: не уверен, что эта конкретная проблема plagues. NET. идея заключалась в том, чтобы проиллюстрировать фактический дизайн / оптимизацию, выполненную на языке сбора мусора, который был, в большинстве случаев, умный и полезный, но может привести к нежелательному использованию памяти.

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

Comments

    Ничего не найдено.