question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Avoid memory leak for IDisposable/NonShared exports

See original GitHub issue

Consider the sample below. When the exported type implements IDisposable the container keeps a reference to all created values, even if they are non-shared. This easily causes significant memory leaks.

What is the recommended pattern here?

using System;
using System.ComponentModel.Composition;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.VisualStudio.Composition;
using CreationPolicy = System.ComponentModel.Composition.CreationPolicy;

namespace MefTest
{
    [Export(typeof(ViewModel)), PartCreationPolicy(CreationPolicy.NonShared)]
    public class ViewModel : IDisposable
    {
        private byte[] bytes;
        public ViewModel() => bytes = new byte[100000]; // Leak
        public void Dispose() {}
    }

    class Program
    {
        static void Main(string[] args)
        {
            var t = InitMef();
            t.Wait();

            var container = t.Result;

            for (var i = 0; i < 100; i++)
            {
                var model = container.GetExportedValue<ViewModel>();
                model.Dispose(); // Container keeps a reference here!
            }

            // NOTE: I want to keep my container.
            // How do I release the memory allocated above?
            // container.Dispose();
        }

        private static async Task<ExportProvider> InitMef()
        {
            var discovery = PartDiscovery.Combine(new AttributedPartDiscoveryV1(Resolver.DefaultInstance));

            var catalog = ComposableCatalog.Create(Resolver.DefaultInstance)
                .AddParts(await discovery.CreatePartsAsync(Assembly.GetExecutingAssembly()))
                .WithCompositionService();

            var config = CompositionConfiguration.Create(catalog);
            var epf = config.CreateExportProviderFactory();
            var exportProvider = epf.CreateExportProvider();

            return exportProvider;
        }
    }
}

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:2
  • Comments:9 (7 by maintainers)

github_iconTop GitHub Comments

1reaction
AArnottcommented, May 28, 2019

Yes, it’s by design that the container maintains references to disposable values. But once a NonShared disposable value has been disposed of by itself, I believe there’s no reason for the container to retain its reference.

I imagine the ExportLifetimeContext<T> or Export<T> Dispose() method should not only dispose the T value but remove the reference from the container.

But now that I look at your code a bit more, I see you don’t have either of those wrappers, since you’re calling GetExportedValue<T> so all you get back is a T. So in fact this “leak” may in fact be by design. We’ll have to review.

In the meantime, can you try using an ExportFactory<T> instead to create the instances you need? That will give you the wrapper, and that wrapper may already release the container’s reference when you dispose the value.

0reactions
AArnottcommented, Sep 23, 2020

I’m taking a look at this now.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Avoid Memory Leaks with Third-Party Libraries
In this article, you will learn how to avoid memory leaks when using third-party libraries or frameworks in embedded software projects, by following...
Read more >
How can I handle the memory leakage problems?
The very best way to handle the memory leakage problem is to develop patience. ... If for example you do an export using...
Read more >
Memory leak involving a class exported from a DLL
I read this excellent article by Eli Bendersky on exporting C++ classes from a DLL. I want to make a class that creates...
Read more >
9 ways to avoid memory leaks in Android | by Anitaa Murthy
There are a lot of articles on memory leaks and how to fix them. ... How to solve this? Option 1: Cancel timer...
Read more >
Preventing and Debugging Memory Leaks in Node.js
Learn about Node.js memory leaks and their causes, how to debug and fix them, prevention best practices, methods for monitoring leaks.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found