Порядок удаления памяти и GC в C # - PullRequest
7 голосов
/ 15 ноября 2010

Что на самом деле происходит в C #, когда:

1) A method gets invoked.
2) The method allocates memory (e.g. MemoryStream mm = new MemoryStream()).
3) An exception occurs in the method which is caught by the invoking classes.

Освобождается ли ресурс "mm" сборщиком мусора? Это угроза безопасности (например, DoS)?

P.S .: Я знаю, что лучше всего явно освобождать любой выделенный ресурс. Это будет означать использование блока «using» или «try / catch / finally».

Ответы [ 4 ]

11 голосов
/ 15 ноября 2010

Ресурс "mm" освобождается сборщиком мусора?

Когда он умрет, да. В конце концов, ГХ запустится и освободит память, если на нее нет ссылок.

Это угроза безопасности?

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

Чтобы ответить на ваш вопрос, нам нужно знать:

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

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

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

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

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

5 голосов
/ 15 ноября 2010

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

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

Теперь ... это дыра в безопасности?Зависит от ситуации.Да, для DoS вполне возможно выделять слишком много памяти;это проблема любой системы, но, честно говоря, с ней редко приходится иметь дело, если только ваш код не особенно плох в отношении зависания памяти.Иногда вы можете захотеть использовать ValueType struct для временных значений;все зависит от ситуации, нет единого правильного способа сделать что-то.

Относительно вашего PS: в .NET не рекомендуется явно освобождать каждый выделенный ресурс;Лучше всего явно освобождать неуправляемые ресурсы.Лучше всего оставлять управляемые ресурсы на уровне , если только не обнаружит проблем с производительностью, после чего вы можете рассмотреть более драконовские методы управления памятью.Пусть GC сделает свою работу правильно, и в 99 из 100 случаев все будет хорошо.

Для получения дополнительной информации:

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

1 голос
/ 15 ноября 2010

Я просто хотел добавить некоторые пояснения относительно оператора using.

Любой объект, который имеет дело с неуправляемыми ресурсами (такими как File и Font), должен реализовывать интерфейс IDisposable ... Что и есть Использование оператора работает с.

Цель IDisposable и оператора Using состоит в том, чтобы гарантировать, что неуправляемые ресурсы должным образом очищаются, а не остаются без дела после их использования.

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

Для MS:" Как правило, когда вы используете объект IDisposable, вы должны объявить и создать его экземпляр в операторе using. "

1 голос
/ 15 ноября 2010

вы должны использовать структуру thr try / catch / finally и вызвать функцию mm.Disponse () в блок finally, чтобы освободить все неуправляемые ресурсы.В случае memoryStream он вызывает Stream.Dispose (), который, в свою очередь, будет располагать событие, созданное в результате вызова асинхронных методов (.BeginRead (), .BeginWrite ()), если они не были завершены до потокабыл завершен

...