У меня такой код:
MemoryStream foo(){
MemoryStream ms = new MemoryStream();
// write stuff to ms
return ms;
}
void bar(){
MemoryStream ms2 = foo();
// do stuff with ms2
return;
}
Есть ли шанс, что выделенный мною MemoryStream каким-то образом не удастся удалить позже?
У меня есть экспертная оценка, в которой я настаиваю на том, чтобы я закрыл это вручную, и я не могу найти информацию, чтобы сказать, есть ли у него действительная точка или нет.
c#
.net
memory-leaks
memorystream
Coderer
источник
источник
Ответы:
Если что-то одноразовое, вы всегда должны утилизировать это. Вы должны использовать
using
оператор в своемbar()
методе, чтобы убедиться, что онms2
будет удален.В конечном итоге он будет очищен сборщиком мусора, но всегда рекомендуется вызывать Dispose. Если вы запустите FxCop в своем коде, он пометит это как предупреждение.
источник
Вы ничего не пропустите - по крайней мере, в текущей реализации.
Вызов Dispose не очистит память, используемую MemoryStream, быстрее. Это будет остановить поток от того , жизнеспособной для чтения / записи вызовов после вызова, которые могут или не могут быть полезными для вас.
Если вы абсолютно уверены, что никогда не хотите переходить от MemoryStream к потоку другого типа, не вызовите Dispose. Тем не менее, это вообще хорошая практика отчасти потому , что если вы когда - либо сделать изменения , чтобы использовать другой поток, вы не хотите , чтобы получить укусили ошибкой труднодоступной находки , потому что вы выбрали легкий путь рано. (С другой стороны, есть аргумент ЯГНИ ...)
Другая причина сделать это в любом случае заключается в том, что новая реализация может вводить ресурсы, которые будут освобождены в Dispose.
источник
IDisposable
является особым случаем, идущим вразрез с обычной передовой практикой, вы можете утверждать, что это тот случай, который вам не следует делать до тех пор, пока вам действительно не понадобится, в соответствии с YAGNI принцип.Да , есть утечка , в зависимости от того, как вы определяете ТРАВИТ и сколько СПУСТЯ вы имеете в виду ...
Если под утечкой вы имеете в виду «память остается выделенной, недоступной для использования, даже если вы закончили ее использовать», а под последним вы имеете в виду в любое время после вызова dispose, тогда да, может быть утечка, хотя она не постоянная (т.е. жизнь вашего приложения).
Чтобы освободить управляемую память, используемую MemoryStream, вам нужно отменить ссылку на нее, аннулировав вашу ссылку на нее, чтобы она сразу стала подходящей для сборки мусора. Если вы этого не сделаете, вы создадите временную утечку с момента, когда вы закончите ее использовать, до тех пор, пока ваша ссылка не выйдет из области видимости, потому что в это время память не будет доступна для выделения.
Преимущество оператора using (по сравнению с простым вызовом dispose) заключается в том, что вы можете ЗАЯВИТЬ свою ссылку в операторе using. Когда оператор using завершается, вызывается не только dispose, но и ваша ссылка выходит за пределы области видимости, фактически обнуляя ссылку и немедленно делая ваш объект подходящим для сборки мусора, не требуя напоминания о написании кода «reference = null».
Отсутствие немедленной отмены ссылки на что-то не является классической «постоянной» утечкой памяти, но определенно имеет тот же эффект. Например, если вы сохраните ссылку на MemoryStream (даже после вызова dispose) и немного ниже в своем методе вы попытаетесь выделить больше памяти ... память, используемая вашим потоком памяти, на который все еще ссылается, не будет доступна вам, пока вы не аннулируете ссылку или она не выйдет за пределы области видимости, даже если вы вызвали команду dispose и закончили ее использование.
источник
Вызов
.Dispose()
(или заворачиваниеUsing
) не требуется.Причина, по которой вы звоните,
.Dispose()
- как можно скорее освободить ресурс .Подумайте, например, о сервере переполнения стека, где у нас ограниченный набор памяти и тысячи входящих запросов. Мы не хотим ждать плановой сборки мусора, мы хотим освободить эту память как можно скорее, чтобы она была доступна для новых входящих запросов.
источник
FileStream
объектов и другого стиля дляMemoryStream
объектов?На этот вопрос уже дан ответ, но я просто добавлю, что старый добрый принцип сокрытия информации означает, что в какой-то момент вы можете захотеть провести рефакторинг:
кому:
Это подчеркивает, что вызывающим абонентам не нужно заботиться о том, какой тип Stream возвращается, и дает возможность изменить внутреннюю реализацию (например, при имитации для модульного тестирования).
Тогда у вас могут возникнуть проблемы, если вы не использовали Dispose в своей реализации панели:
источник
Все потоки реализуют IDisposable. Оберните свой поток памяти в оператор using, и все будет в порядке. Блок using гарантирует, что ваш поток будет закрыт и удален, несмотря ни на что.
где бы вы ни вызывали Foo, вы можете использовать (MemoryStream ms = foo ()), и я думаю, что все должно быть в порядке.
источник
У вас не будет утечки памяти, но ваш рецензент кода правильно указал, что вам следует закрыть поток. Это вежливо.
Единственная ситуация, в которой может произойти утечка памяти, - это когда вы случайно оставляете ссылку на поток и никогда не закрываете его. Вы все еще не действительно утечки памяти, но которые без необходимости расширения количества времени , которое вы утверждаете использовать его.
источник
Я бы рекомендовал обертывание MemoryStream в
bar()
вusing
заявлении , главным образом , для последовательности:.Dispose()
, но возможно, что в какой-то момент в будущем это может, или вы (или кто-то другой в вашей компании) можете заменить ее своим собственным MemoryStream, который делает, и т. Д.Еще одна вещь, которую я обычно делаю в таких случаях, как
foo()
создание и возврат IDisposable, - это обеспечение того, чтобы любой сбой между созданием объекта иreturn
объектом был перехвачен исключением, удалялся объект и повторно генерировался исключение:источник
Если объект реализует IDisposable, вы должны вызвать метод .Dispose, когда закончите.
В некоторых объектах Dispose означает то же, что и Close, и наоборот, в этом случае подходит любой вариант.
Теперь, по вашему конкретному вопросу, нет, утечки памяти не будет.
источник
Я не эксперт .net, но, возможно, проблема здесь в ресурсах, а именно в дескрипторе файла, а не в памяти. Я предполагаю, что сборщик мусора в конечном итоге освободит поток и закроет дескриптор, но я думаю, что всегда было бы лучше всего закрыть его явно, чтобы убедиться, что вы сбрасываете содержимое на диск.
источник
Удаление неуправляемых ресурсов в языках со сборкой мусора не является детерминированным. Даже если вы вызываете Dispose явно, у вас нет абсолютно никакого контроля над фактическим освобождением резервной памяти. Dispose неявно вызывается, когда объект выходит за пределы области видимости, будь то выход из оператора using или всплытие стека вызовов из подчиненного метода. При этом, иногда объект может фактически быть оболочкой для управляемого ресурса (например, файла). Вот почему рекомендуется явно закрывать в операторах finally или использовать оператор using. ура
источник
MemorySteram - это не что иное, как массив байтов, который является управляемым объектом. Забудьте об удалении или закрытии, это не имеет побочных эффектов, кроме чрезмерной доработки.
Просто проверьте метод constuctor или flush для MemoryStream в отражателе, и станет ясно, почему вам не нужно беспокоиться о его закрытии или удалении, кроме как просто для соблюдения хорошей практики.
источник