2010-11-15 2 views
7

Что на самом деле происходит в C#, когда:Порядок утилизации памяти и GC в 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. 

ли ресурс «мм» получает освобождены сборщиком мусора? Является ли это угрозой безопасности (например, DoS)?

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

ответ

5

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

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

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

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

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

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

+1

Может быть, я ошибаюсь, но я не совсем согласен с последним абзацем. Помимо 'Dispose()' 'MemoryStream' не делает много (без неуправляемых ресурсов), так как нет ссылки на' MemoryStream', нет никакой разницы между исключением или нормальным выходом и DoS на таком метод просто вызовет GC более чем необходимо. Я думаю, что если у вас есть уязвимость DoS, это не ваша самая большая проблема. Вы согласны или у вас другое мнение? –

+0

@Pieter: Я извиняюсь, что, возможно, я не понимаю, что вы говорите, но я попытаюсь ответить: я согласен, что вы должны «Dispose» из 'MemoryStream'; он «сбрасывает» буфер и закрывает поток, предотвращая дальнейшую запись (при условии, что он используется для записи). Но я думаю, что первоначальный искатель использовал только «MemoryStream» в качестве примера для любой выделенной памяти; он мог бы просто быть «новым Foo» и имел бы в виду то же самое для его вопроса. – Randolpho

+0

@Pieter (продолжение): Как вы говорите, нет разницы между исключением и нормальным выходом, кроме потока программы, и я согласен, что если есть уязвимость DoS, она, скорее всего, будет находиться где-то в другом месте. Я думаю, что в большинстве случаев выделение памяти во время вызова метода (с помощью 'new Anything()') не является уязвимостью DoS, если только ваш метод не особенно плох в распределении много временной памяти. Даже тогда это меньше «DoS-уязвимости» и более «неаккуратного программирования». – Randolpho

1

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

+0

Хотя я согласен с вашими предложениями относительно использования MemoryStream, я думаю, что MemoryStream в оригинальной записи был скорее примером; Я думаю, что @bonobo интересовался какой-либо выделенной памятью, и так же легко мог быть объект Foo, который был выделен на шаге 2. – Randolpho

11

Предоставляет ли ресурс «мм» сборщик мусора?

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

Это риск для безопасности?

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

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

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

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

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

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

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

+0

Спасибо, что подняли вопрос о том, что является или не является уязвимостью в целом. Это само по себе стоит +1. – Randolpho

1

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

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

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

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

Per MS: «Как правило, при использовании IDisposable объекта, вы должны объявить и создать его экземпляр в использовании заявления»

Смежные вопросы