Why is there a memory leak when I do not .Dispose() Bitmaps that I .Save() to a MemoryStream?

后端 未结 3 1759
灰色年华
灰色年华 2021-01-06 13:39

Say I create a Bitmap

Bitmap bitmap = new Bitmap(320, 200);

When I write it to some stream (in my case, it\'s a HttpResponseStream, as give

3条回答
  •  鱼传尺愫
    2021-01-06 14:21

    I think the issue is the assumption that the GC will magically clean up your objects. However, it may never do so, and here's what I think may be happening:

    Bitmaps use unmanaged resources to hold the bitmap data, and bitmap data is big. So you will be allocating a tiny block of managed memory and a huge block of unmanaged memory for each bitmap.

    So you leave your bitmap lying around for the GC to collect at its leisure. This works well for a lot of objects because soon there is enough memory pressure that the GC collects them to re-use the memory. BUt the GC looks at the managed heap and says "By disposing the uniused objects, I can only recover 64 bytes of memory. I won't bother". It doesn't see the gigabytes of unmanaged resources, just the few bytes on its heap.

    So you need to track and dispose of the bitmaps yourself.

    It is possible that sometimes you have seen it clean up for you. This will be because under sme circumstances (such as when you are disposing other objects like streams with larger memory footprints, or just because it's a tuesday afternoon) it does choose to process the unused blocks of memory, and then your bitmap is disposed at last. But you cannot rely on this happening.

    ...Ramble:

    There were two problems with pointers in the olden days.

    • They could be null, leading to crashing code
    • You could forget to free their memory/resources and get leaks

    So in .net they renamed "pointer" to "reference", added the GC and pretended that the problem didn't exist any more. Except that references can still be null, and programmers do still have to track and manage their resources to avoid leaks - just a little bit less often. I think this is a bad thing - it makes us lazy and inefficient without actually eliminating the underlying problem, so then it comes back and bites us, and we end up writing reams of Dispose logic where we used to just have a simple 'delete' in our destructors.

提交回复
热议问题