Q:

How can I resolve my CoreGraphics Memory Leak without crashing?

I have a code iterator that is a test function for conversion of raw data to UIImage objects for file storage. I have two failure paths or options. I can fail:
A.)By having a leak (instruments doesn't show it--instruments all allocations seems to be stable, I have to iterate a number of times say 50 and it will crash running the test function through instruments or normally). Memory appears to be the culprit due to "b" option below. 
B.)I can do a forced release of the CG object within UIImage in which case the app will proceed. Once the iterator completes the test will crash on the very last iteration trying to free the CGImage underneath the image returned from my sub-function.  The iterator will complete it's run no matter how many iterations I request. This would point to the fact I have fixed a leak. So now I'm trying to puzzle together what is special about the very last iteration? (ARC?)
- (UIImage *) convertRGBToUIImage:(unsigned char *) buffer 
                            withWidth:(int) width
                           withHeight:(int) height 
{

   CGColorSpaceRef colorSpace       = nil;
   CGContextRef    context          = nil;
   CGImageRef      ref              = nil;
   UIImage        *retImg           = nil;

   colorSpace = CGColorSpaceCreateDeviceRGB();
   if (colorSpace == NULL)
   {
      NSLog(@"ERROR: allocating color space convert Bitmap\n");
      return nil;
   }

   context = CGBitmapContextCreate (buffer, width, height, 8, width * 4, colorSpace,     kCGImageAlphaPremultipliedLast);
   CGColorSpaceRelease(colorSpace );

   if (context == NULL)
   {
     NSLog(@"ERROR: Context not created!");
     return nil;
   }

   ref = CGBitmapContextCreateImage(context);                                     
   CGContextRelease(context);

   retImg = [UIImage imageWithCGImage:ref];
   CGImageRelease(ref);

   return retImg;
}

iterator basics
for(int i = 0; i < numberiterations; i++)
{ 
    UIImage *completedImage = [phelper convertRGBToUIImage:pBuffer withWidth:width withHeight:height]

    //...save it out or display it

    //Turn on one of the scenarios below

    //scenario "A" -- will leak memory (instruments doesn't seem to turn anything up)
    //ARC free
    //completedImage = nil; //this will leak and fail after ~50 iterations

    //-or-

    //scenario "B" -- will crash on the very last iteration every time but can run x times
    //CGImageRelease([completedImage CGImage];

}

The analysis tool in Xcode prefers scenario 'A' above. Again I can do this and everything seems great but it will not successfully complete the test. I think this points to ARC. I have tried to figure out the __bridge type casting with no success. I can't seem to get the syntax right and perhaps its not the answer to my problem.  Any hints or ideas would be very appreciated.

A:

The reason why Instruments is not showing a leak is that — technically — there is none
What you are seeing is the memory pressure from an @autoreleasepool that is not tight enough:
Your method convertRGBToUIImage:withWidth:withHeight: returns a new autoreleased image, but the closest @autoreleasepool is outside of your loop.
That means that all of those images are not disposed of until the method, in which your loop lives, returns.
This is the reason why you see your memory consumption growing with each iteration in scenario A and your application crash after the loop in scenario B:
UIImage is — mostly — an Objective-C wrapper around CGImageRef so that your additional CGImageRelease in scenario B pulls the backing store out from under the UIImage’s feet. This backing store happens to be the memory hungry part of the UIImage so your drastic increase in memory consumption almost vanishes.
When the @autoreleasepool is drained after the method with the loop returned, it disposes of all the temporary UIImage instances which — in turn — want to dispose of their backing-CGImageRef…and boom there goes the program.
The trick is to create your own @autoreleasepool inside the loop:
for (int i = 0; i < numberiterations; i++) {
    @autoreleasepool {
        // your old iteration body comes here
    }
}

Now, scenario A will behave as expected and scenario B will crash immediately at the end of the first iteration — which is to be expected, as well.

And now for some serious brain-f**k:
If you run your original code under ARC in a “Release” scheme, (i.e. with the compiler flag -Os aka “fastest smallest”) scenario A will most likely not crash!
The reason for this seemingly bizarre behavior is, that ARC garnishes your code with a special set of C-functions that perform the actual memory management — and because these functions are constant (which method calls in Objective-C aren’t necessarily) the compiler can optimize certain combinations of them away.
This leads to the UIImage never being inserted into an autorelease-pool in the first place and, thus, being disposed of after each iteration of the loop.

