Bug 13671 - CGImageDestination leaks the Handle, creating a memory leak
Summary: CGImageDestination leaks the Handle, creating a memory leak
Status: RESOLVED FIXED
Alias: None
Product: iOS
Classification: Xamarin
Component: Xamarin.iOS.dll ()
Version: 6.4.0
Hardware: PC Mac OS
: --- normal
Target Milestone: Untriaged
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2013-07-31 21:28 UTC by Adrian Gallero
Modified: 2013-08-01 08:13 UTC (History)
2 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED FIXED

Description Adrian Gallero 2013-07-31 21:28:13 UTC
CGImageDestination.FromData and CGImageDestination.FromURL never dispose the internal CGImageDestination handle.

Steps to reproduce:
1)Create a new single view iOS app, add a button.
2)In the event handle write:
       partial void test(NSObject sender)
        {
         
            using (NSData data = NSData.FromArray(new byte[] { 0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x01, 0x00, 0x01, 0x00, 0x80, 0x00, 0x00, 
                0x05, 0x04, 0x04, 0x00 ,0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x02, 0x02, 0x44, 0x01, 0x00, 0x3B}))
            {
                for (int i = 0; i < 100000; i++)
                {              
                    using (MonoTouch.ImageIO.CGImageDestination imgDest = MonoTouch.ImageIO.CGImageDestination.FromData(data, "public.png", 1))
                    {
                    }
                }
            }
            GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
        }


3) Look at the memory usage in instrument, the CGImage handles are never released.


Proposed fix:
FromData and FromURL call new CGImageDestination(p):

public static CGImageDestination FromData (NSData data, string typeIdentifier, int imageCount, CGImageDestinationOptions options)
		{
  <snip>

			var ret = p == IntPtr.Zero ? null : new CGImageDestination (p);
			if (dict != null)
				dict.Dispose ();
			return ret;
		}

but the constructor for CGImageDestination(p) is:

// invoked by marshallers
		internal CGImageDestination (IntPtr handle) : this (handle, false)
		{
			this.handle = handle;
		}
Which calls the constructor with "owns = false", so the handle is retained. By the way, the line this.handle = handle is redundant, since this(handle, false) will assign the handle anyway.

So the correct thing to do is to call the constructor with "owns = true":

var ret = p == IntPtr.Zero ? null : new CGImageDestination (p, true);

This is the way it is called in CGImageSource too.
Comment 1 Adrian Gallero 2013-07-31 21:29:55 UTC
Just a note, this is a *big* memory leak, since the CGImageDestination not freeing will mean the full CGImages are not freed either. For big images this can create a crash very soon.

This is a critical bug for me (and for everyone using CGImageDestination)
Comment 2 Rolf Bjarne Kvinge [MSFT] 2013-08-01 08:13:54 UTC
Fixed. This fix will be included in 6.4.2.

maccore/master: 36fbaec3bfe670044f91931ff7c625735c0fa8ff
monotouch/master-3.0: 73e151d9f521f826c3f98f114aa8752924db65f2
monotouch/monotouch-6.4-series: be06e3f33e1a9d82797b1d1b1b961de17ac68c77