Search code examples
c#json.netdotnetzip

Memory leak in debug mode only


I have this code:

using (var memoryStream = new MemoryStream())
{
    using (var streamWriter = new StreamWriter(memoryStream))
    {
        var list = new List<Actor>();
        for (var i = 0; i < 1000000; i++)
        {
            list.Add(new Actor("lorem ipsum"));
        }

        using (var serializedContent = new MemoryStream())
        {
            streamWriter.WriteLine(JsonConvert.SerializeObject(list));
            streamWriter.Flush();
            serializedContent.Seek(0, SeekOrigin.Begin);
            using (ZipFile zip = new ZipFile())
            {
                zip.AddEntry("message.txt", serializedContent);
                zip.Save("Archive.zip");
            }
        }
    }
}

while (true)
{
    GC.Collect();
    GC.WaitForPendingFinalizers();
    GC.WaitForFullGCComplete();
    GC.Collect();
    Console.WriteLine("completed");
    Console.ReadKey();
}

The problem is that a memory leak only appears in debug version, while in release it fully cleans after itself. Any ideas why could this be happening?

Edit. I noticed that the problem disappears if I remove that part where I try to add files to zip archive. What could be the difference between debug and release versions with this code? I can't see the problem, because archiving part is executed within the using statement.


Solution

  • Try wrapping your code into a function.

    Take a look at this blogpost:

    The tricky point is that a variable is eligible to be dead once it’s not used anymore. However, it’s up to JIT to determine whether it really wants to report the variable to be dead. In fact, for debuggable code, JIT extends lifetime for every variable to end of the function.

    This means your variable will not be collected, by GC.Collect, because your variable is in the same function and at debugtime still in scope.

    Remember: The garbage collector only removes variable that are not used (not in scope). using is only calling Dispose on an object.