サンプルコードのバグを見つけた
1日悩んだiPhoneアプリのメモリーリーク。
原因は、「The iPhone Developer's Cookbook」のサンプルコード。
// Build a thumb image based on the grayscale percentage
id createImage(float percentage)
{
CGRect aRect = CGRectMake(0.0f, 0.0f, 48.0f, 48.0f);
CGContextRef context = MyCreateBitmapContext(48, 48);
CGContextClearRect(context, aRect);
// Outer gray circle
CGContextSetFillColorWithColor(context, [[UIColor lightGrayColor] CGColor]);
CGContextFillEllipseInRect(context, aRect);
// Inner circle with feedback levels
CGContextSetFillColorWithColor(context, [[UIColor colorWithRed:percentage green:0.0f blue:0.0f alpha:1.0f] CGColor]);
CGContextFillEllipseInRect(context, CGRectInset(aRect, 4.0f, 4.0f));
// Inner gray circle
CGContextSetFillColorWithColor(context, [[UIColor lightGrayColor] CGColor]);
CGContextFillEllipseInRect(context, CGRectInset(aRect, 16.0f, 16.0f));
CGImageRef myRef = CGBitmapContextCreateImage (context);
free(CGBitmapContextGetData(context));
CGContextRelease(context);
return [UIImage imageWithCGImage:myRef];
}
これでは、myRefのRelease時期を逸してしまう。
正確には、こうあるべき。
// Build a thumb image based on the grayscale percentage
id createImage(float percentage)
{
CGRect aRect = CGRectMake(0.0f, 0.0f, 48.0f, 48.0f);
CGContextRef context = MyCreateBitmapContext(48, 48);
CGContextClearRect(context, aRect);
// Outer gray circle
CGContextSetFillColorWithColor(context, [[UIColor lightGrayColor] CGColor]);
CGContextFillEllipseInRect(context, aRect);
// Inner circle with feedback levels
CGContextSetFillColorWithColor(context, [[UIColor colorWithRed:percentage green:0.0f blue:0.0f alpha:1.0f] CGColor]);
CGContextFillEllipseInRect(context, CGRectInset(aRect, 4.0f, 4.0f));
// Inner gray circle
CGContextSetFillColorWithColor(context, [[UIColor lightGrayColor] CGColor]);
CGContextFillEllipseInRect(context, CGRectInset(aRect, 16.0f, 16.0f));
CGImageRef myRef = CGBitmapContextCreateImage (context);
free(CGBitmapContextGetData(context));
CGContextRelease(context);
//return [UIImage imageWithCGImage:myRef];
UIImage *img = [UIImage imageWithCGImage:myRef];
CGImageRelease(myRef);
return img;
}

