Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > утечка памяти


Автор: uranpro 6.4.2010, 15:41
голову сломал, не могу въехать  smile 
есть
Код

    [Serializable]
    public class CustomSerialization<T> : IDisposable
    {
        public MemoryStream GetMStream()
        {
            var stream = new MemoryStream();
            try
            {
                new BinaryFormatter().Serialize(stream, this);
                stream.Position = 0;
                return stream;
            }
            catch
            {
                stream.Close();
                throw;
            }
        }

        public static T GetObjectFromMStream(MemoryStream MStream)
        {
            return (T)new BinaryFormatter().Deserialize(MStream);
        }

        public virtual void Dispose() { }
    }

    [Serializable]
    public class MSTest : CustomSerialization<MSTest>
    {
        public MemoryStream stream { get; set; }

        public override void Dispose()
        {
            stream.Close();
        }
    }

    public static class CopyStream
    {
        public static void Copy(Stream streamIn, Stream streamOut)
        {
            byte[] buffer = new byte[2000];
            int len;
            while ((len = streamIn.Read(buffer, 0, 2000)) > 0)
            {
                streamOut.Write(buffer, 0, len);
            }
            streamOut.Flush();
        }
    }

делаю так
Код

        void AddMemoryInUse(string Msg)
        {
            AddResult(string.Format("Memory in use {0:D} KB, after {1}", GC.GetTotalMemory(false) / 1024, Msg));
        }

        public Form1()
        {
            InitializeComponent();

            AddMemoryInUse("start");

            var msg = new MSTest();

            AddMemoryInUse("msg create");

            var fs = new FileStream("C:\\Trio.avi", FileMode.Open); // весит 4мб
            AddMemoryInUse("fs open");
            msg.stream = new MemoryStream();
            CopyStream.Copy(fs, msg.stream);

            AddMemoryInUse("fs copy to msg.stream");
            
            fs.Close();
            
            AddMemoryInUse("fs.close");

            var ms2 = msg.GetMStream();

            AddMemoryInUse("ms2 = msg.GetMStream");

            msg.Dispose();

            AddMemoryInUse("msg.dispose");

            var msg2 = MSTest.GetObjectFromMStream(ms2);

            AddMemoryInUse("msg2 load from ms2");

            ms2.Close();

            AddMemoryInUse("ms2.close");

            msg2.Dispose();

            AddMemoryInUse("msg2.dispose");
}

результат:
Memory in use 370 KB, after start
Memory in use 370 KB, after msg create
Memory in use 370 KB, after fs open
Memory in use 12191 KB, after fs copy to msg.stream
Memory in use 12199 KB, after fs.close
Memory in use 32214 KB, after ms2 = msg.GetMStream
Memory in use 32214 KB, after msg.dispose
Memory in use 32239 KB, after msg2 load from ms2
Memory in use 32239 KB, after ms2.close
Memory in use 32239 KB, after msg2.dispose

в чем дело ? как с этим бороться ? (кроме GC.Collect(2, GCCollectionMode.Forced))

Автор: Irdis 6.4.2010, 17:37
Дело в том, что GC не обещает собрать мусор в тот же момент, в который на объект пропала ссылка.

http://www.rsdn.ru/article/dotnet/GCnet.xml

Автор: uranpro 6.4.2010, 18:06
я знаю =) да и ссылки не пропадали. меня интересует, почему метод .Close()/.Dispose() stream`a не освободил ресы ?

Автор: PashaPash 6.4.2010, 18:55
uranpro, .Close()/.Dispose() не освобождает память. Память в .net освобождается только в момент сборки мусора. Если после GC.Collect(2, GCCollectionMode.Forced) память освобождается - то это как раз не утечка. 

Автор: uranpro 7.4.2010, 10:18
понятно, но она занимает много времени... и освобождает все, а мне нужно только stream`ы

Добавлено через 2 минуты и 33 секунды
точнее не все, а мусор

Автор: PashaPash 7.4.2010, 14:39
uranpro, а ты не вызывай сборку мусора. Вызывая сборку всех поколений, с Forced и ожиданием завершения ты практически выбрасываешь все наработки MS по сборке мусора за последние 10 лет smile
Зачем тебе нужно память из-под стримов освободить? Потому что GC.GetTotalMemory показывает пятизначное число, и оно тебе не нравится? Это не повод лезть в самонастраиваемый механизм GC smile

Методы класса GC вообще нельзя вызывать без полного понимания механизма работы сборщика. Забудь о них и спи спокойно.

Автор: uranpro 8.4.2010, 12:37
с этой памятью... что-то я все напутал. ведь gc сам сделает все что нужно. 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)