1

I have the following function to convert a byte array of pixels into an image. However, I have a memory leak in the line:

unpackedImage = UIImage.FromImage(context.ToImage());

When I comment out the line above, the leak goes away. The leak is so bad that iOS is killing my app within about 30 seconds of startup. It's because of this line of code.

How do I prevent this memory leak? Is there a better way to do what I am trying to do?

    public static void DrawCustomImage2(IntPtr buffer, int width, int height, int bytesPerRow, CGColorSpace colSpace, byte[] rawPixels, ref UIImage unpackedImage)
    {
        GCHandle pinnedArray = GCHandle.Alloc(rawPixels, GCHandleType.Pinned);
        IntPtr pointer = pinnedArray.AddrOfPinnedObject();

        // Set a grayscale drawing context using the image buffer
        CGBitmapContext context = new CGBitmapContext(pointer, width, height, 8, bytesPerRow, colSpace, CGImageAlphaInfo.None);

        // Turning off interpolation and Antialiasing is supposed to speed things up
        context.InterpolationQuality = CGInterpolationQuality.None;
        context.SetAllowsAntialiasing(false);

        try
        {
            unpackedImage = UIImage.FromImage(context.ToImage());   // Convert the drawing context to an image and set it as the unpacked image
        } finally
        {
            pinnedArray.Free();
            if (context != null)
                context.Dispose();
        }
    }

Here is the profiling screenshot (checked items all disappear when the critical line of code is commented out). You can see how the checked items (especially the Malloc) grow over time.

Profiling Screenshot

Here is the zoom-in view on the Malloc 1.50KB. You can see in the Extended Detail pane on the right that it is calling CGBitmapContextCreateImage and CGDataProviderCreateWithCopyOfData and then a malloc. Malloc 1.50KB Profiling Screenshot

Here is the profiling screenshot with Rolf's suggestion. I ran the image loop twice. You can see that it cleans up the extra memory at the end of the first loop, but the system didn't clean it up fast enough the second time and iOS killed my app (you can see the low memory warning flags in the top right corner). enter image description here

4

1 回答 1

4

Do it like this:

using (var pool = new NSAutoreleasePool ()) {
    using (var img = context.ToImage ()) {
        unpackedImage = UIImage.FromImage (img); 
    }
}
于 2012-05-22T10:21:16.367 回答