1

Resolved

Memory leak in XamObject class

description

The MultipartXStreamWrite and MultipartXStreamRead methods both create a MultipartXStream but do not dispose of it. Internally a MultipartXStream contains an array of XStream objects of which the constructor adds a reference in a static list called streamObjects. If these XStream objects are not disposed of (which triggers the base Stream class to call the Close method) instances are never removed from the list and a memory leak results. This can be rectified by a using statement in the MultipartXStreamWrite and MultipartXStreamRead methods in the XamObject class as shown below:
 
    public void MultipartXStreamWrite(Stream s, XString fieldName, XString mimeType, int parts, bool binding)
    {
        using (Helpers.MultipartXStream str = CreateMultipartXStream(fieldName, mimeType, parts, s.Length, binding))
        {
            long offset = 0;
            int i = 0;
            Thread[] t = new Thread[parts];
 
            for (i = 0; i < parts; i++)
            {
                t[i] = new MultipartThread(s, str.streams[i], offset, (int)str.PartLength(i));
                t[i].Start();
 
                offset += str.PartLength(i);
            }
 
            for (i = 0; i < parts; i++)
                t[i].Join();
        }
    }
 
 
    public void MultipartXStreamRead(Stream s, XString fieldName)
    {
        long offset = 0;
        int i = 0;
        using (Helpers.MultipartXStream str = OpenMultipartXStream(fieldName))
        {
            int parts = (int)str.streams.Length;
            Thread[] t = new Thread[parts];
 
            for (i = 0; i < parts; i++)
            {
                t[i] = new MultipartThread(str.streams[i], s, offset, (int)str.PartLength(i));
                t[i].Start();
 
                offset += str.PartLength(i);
            }
 
            for (i = 0; i < parts; i++)
                t[i].Join();
 
        }
    }

comments

gstuartemc wrote Jan 20, 2010 at 10:12 PM

Sean - I agree that utilizing a "using" clause will force that to happen sooner and can be added in to the next release, but surely after the object goes out of scope it will eventually get Garbage Collected (because the MultipartXStream is IDisposable)?

In other words, is the leak not just a temporary failure to release memory (that will eventually be cleaned up by GC) rather than a real leak (which inly gets released when the process terminates)?

seanthomson wrote Jan 21, 2010 at 5:35 AM

You're absolutely right that when the garbage collector picks up the MultipartXStream it will dispose of each internal XStream and consequently the static references to them, Stuart, so it's not a true memory leak just a failure to release memory on the heap.

I came across this by profiling active object references after I found memory grew pretty dramatically during a bulk load test I was performing. If you don't eagerly dispose of the streams you're going to incur garbage collection more frequently than necessary so it's probably worth doing regardless. I was unsure of what effect delaying the call to XStream_Close in xam.dll would have so I erred on the side of caution here.

gstuartemc wrote Jan 21, 2010 at 2:40 PM

Thanks Sean - I will add more vigilant user memory management (via a using clause) into the next release. Just wanted to be sure that my understanding of the issue was correct.

wrote Jan 21, 2010 at 2:41 PM

wrote Jan 22, 2010 at 3:35 PM

wrote Jan 22, 2010 at 3:35 PM

wrote Feb 2, 2013 at 1:32 AM

wrote May 14, 2013 at 9:03 PM

wrote May 14, 2013 at 9:03 PM

wrote Jun 12, 2013 at 1:15 AM