Почему .NET не может иметь утечки памяти? - PullRequest
57 голосов
/ 26 марта 2010

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

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

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

Ответы [ 16 ]

1 голос
/ 03 августа 2010

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

Ниже приведен класс Брэда Абрамса по проектированию библиотек классов .NET

"Ну, во-первых, конечно, нет утечек памяти, верно? Нет? Есть утечки памяти? Ну, есть утечки памяти другого типа. Как насчет этого? Итак, тип памяти утечка, которой у нас нет, это то, что в старом мире вы использовали malloc для некоторой памяти, а затем забыли сделать бесплатную или добавить ссылку и забыли сделать релиз или что-то еще в паре. И в новом мире сборщик мусора в конечном итоге владеет всей памятью, и сборщик мусора освободит этот материал, когда больше нет ссылок. Но все еще могут быть утечки, верно? Каковы утечки? Хорошо, если вы сохраните ссылку на этот объект жив, тогда сборщик мусора не может его освободить. Так много раз, что происходит, вы думаете, что избавились от всего этого графа объектов, но есть еще один парень, который держит его со ссылкой, и тогда вы застряли. Сборщик мусора не может освободить это, пока вы не отбросите все ссылки на него.

Другой, я думаю, большой вопрос. Нет проблем с владением памятью. Если вы прочитаете документацию по WIN32 API, вы увидите, хорошо, я сначала выделю эту структуру и передам ее, а затем вы ее заполните, а затем я ее освобожу. Или я сообщу вам размер, и вы выделите его, а затем я освобожу его позже, или вы знаете, что все эти споры идут о том, кому принадлежит эта память и где она должна быть освобождена. И много раз разработчики просто разочаровываются в этом и говорят: «Хорошо, что угодно. Ну, это будет бесплатно, когда приложение закроется », и это не очень хороший план.

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

Полная стенограмма

1 голос
/ 26 марта 2010

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

1 голос
/ 26 марта 2010

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

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

0 голосов
/ 14 апреля 2010

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

0 голосов
/ 26 марта 2010

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

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

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

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

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

0 голосов
/ 26 марта 2010

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

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

...