喜欢这篇文章:
我遇到了类似的问题。永远不会释放create_bitmap_data_provider
中来自malloc的指针。我已经验证了相关的图像对象最终被释放,而不是提供者的分配。我应该明确地创建数据提供程序并以某种方式管理它的内存吗?看起来像是黑客。
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL, blah blah blah);
CGColorSpaceRelease(colorSpace);
// ... draw into context
CGImageRef imageRef = CGBitmapContextCreateImage(context);
UIImage * image = [[UIImage alloc] initWithCGImage:imageRef];
CGImageRelease(imageRef);
CGContextRelease(context);
在下面的fbrereto回答之后,我将代码更改为:
- (UIImage *)modifiedImage {
CGSize size = CGSizeMake(width, height);
UIGraphicsBeginImageContext(size);
CGContextRef context = UIGraphicsGetCurrentContext();
// draw into context
UIImage * image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image; // image retainCount = 1
}
// caller:
{
UIImage * image = [self modifiedImage];
_imageView.image = image; // image retainCount = 2
}
// after caller done, image retainCount = 1, autoreleased object lost its scope
不幸的是,这仍然表现出相同的问题,即水平翻转图像的副作用。它似乎在内部对CGBitmapContextCreateImage做了同样的事情。
我已经验证了我的对象dealloc
被调用了。在我发布_imageView.image
之前,_imageView
和_imageView
上的retainCount都是1。这真的没有意义。其他人似乎也有这个问题,我是最后一个怀疑SDK的人,但这里可能有iPhone SDK错误???
答案 0 :(得分:4)
看起来问题是你发布了一个指向返回的CGImage
的指针,而不是CGImage
本身。随着持续增长的分配和最终的应用程序崩溃,我也遇到过类似的问题。我通过分配CGImage
而不是CGImageRef
来解决这个问题。更改后,在具有分配的Insturments中运行代码,您不应再看到malloc的永久内存消耗。如果您使用类方法imageWithCGImage
,您也不必担心稍后自动释放UIImage
。
我在PC上输入了这个,所以如果你把它放到XCode中你可能有语法问题,我提前道歉;校长也很健全。
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL, blah blah blah);
CGColorSpaceRelease(colorSpace);
// ... draw into context
CGImage cgImage = CGBitmapContextCreateImage(context);
UIImage * image = [UIImage imageWithCGImage:cgImage];
CGImageRelease(cgImage);
CGContextRelease(context);
return image;
答案 1 :(得分:3)
我遇到了这个问题,它让我疯了几天。经过多次挖掘并注意到使用仪器的CG栅格数据泄漏。
这个问题似乎存在于CoreGraphics中。我的问题是当我在一个紧凑的循环中使用CGBitmapContextCreateImage时,它会在一段时间内保留一些图像(每个800kb)并且这会慢慢泄露出去。
在使用Instruments进行几天跟踪后,我发现一种解决方法是使用CGDataProviderCreateWithData方法。有趣的是输出是相同的CGImageRef,但这次没有在Core by Core图形中使用CG Raster Data而且没有泄漏。我假设这是一个内部问题或者是滥用它。
以下是保存我的代码:
@autoreleasepool {
CGImageRef cgImage;
CreateCGImageFromCVPixelBuffer(pixelBuffer,&cgImage);
UIImage *image= [UIImage imageWithCGImage:cgImage scale:1.0 orientation:UIImageOrientationUp];
// DO SOMETHING HERE WITH IMAGE
CGImageRelease(cgImage);
}
关键是在下面的方法中使用CGDataProviderCreateWithData。
static OSStatus CreateCGImageFromCVPixelBuffer(CVPixelBufferRef pixelBuffer, CGImageRef *imageOut)
{
OSStatus err = noErr;
OSType sourcePixelFormat;
size_t width, height, sourceRowBytes;
void *sourceBaseAddr = NULL;
CGBitmapInfo bitmapInfo;
CGColorSpaceRef colorspace = NULL;
CGDataProviderRef provider = NULL;
CGImageRef image = NULL;
sourcePixelFormat = CVPixelBufferGetPixelFormatType( pixelBuffer );
if ( kCVPixelFormatType_32ARGB == sourcePixelFormat )
bitmapInfo = kCGBitmapByteOrder32Big | kCGImageAlphaNoneSkipFirst;
else if ( kCVPixelFormatType_32BGRA == sourcePixelFormat )
bitmapInfo = kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst;
else
return -95014; // only uncompressed pixel formats
sourceRowBytes = CVPixelBufferGetBytesPerRow( pixelBuffer );
width = CVPixelBufferGetWidth( pixelBuffer );
height = CVPixelBufferGetHeight( pixelBuffer );
CVPixelBufferLockBaseAddress( pixelBuffer, 0 );
sourceBaseAddr = CVPixelBufferGetBaseAddress( pixelBuffer );
colorspace = CGColorSpaceCreateDeviceRGB();
CVPixelBufferRetain( pixelBuffer );
provider = CGDataProviderCreateWithData( (void *)pixelBuffer, sourceBaseAddr, sourceRowBytes * height, ReleaseCVPixelBuffer);
image = CGImageCreate(width, height, 8, 32, sourceRowBytes, colorspace, bitmapInfo, provider, NULL, true, kCGRenderingIntentDefault);
if ( err && image ) {
CGImageRelease( image );
image = NULL;
}
if ( provider ) CGDataProviderRelease( provider );
if ( colorspace ) CGColorSpaceRelease( colorspace );
*imageOut = image;
return err;
}
static void ReleaseCVPixelBuffer(void *pixel, const void *data, size_t size)
{
CVPixelBufferRef pixelBuffer = (CVPixelBufferRef)pixel;
CVPixelBufferUnlockBaseAddress( pixelBuffer, 0 );
CVPixelBufferRelease( pixelBuffer );
}
答案 2 :(得分:0)
而不是手动创建CGContextRef,我建议您使用this post中演示的UIGraphicsBeginImageContext
。可以找到关于该组例程的更多细节here。我相信它有助于解决这个问题,或者至少可以减少你自己管理的记忆。
更新:
鉴于新代码,retainCount
的{{1}}因为它来自函数将为1,并将其分配给imageView的图像将导致它碰到2.此时取消分配imageView会使UIImage
的{{1}}为1,从而导致泄漏。然后,在将retainCount
分配给imageView后,将UIImage
传递给UIImage
非常重要。它可能看起来有点奇怪,但它会使release
正确设置为1。
答案 3 :(得分:0)
你不是唯一有这个问题的人。我在CGBitmapContextCreateImage()方面遇到了重大问题。当您打开 Zombie 模式时,它甚至会警告您内存被释放两次(当情况不是这样时)。将CG *东西与UI *东西混合时肯定存在问题。我还在试图弄清楚如何解决这个问题。
旁注:调用 UIGraphicsBeginImageContext 不是线程安全的。小心。
答案 4 :(得分:0)
这对我有帮助!以下是我用它来解决这个令人讨厌的泄漏问题的方法:
CGImage *cgImage = CGBitmapContextCreateImage(context);
CFDataRef dataRef = CGDataProviderCopyData(CGImageGetDataProvider(cgImage));
CGImageRelease(cgImage);
image->imageRef = dataRef;
image->image = CFDataGetBytePtr(dataRef);
注意,我必须在我的~Image函数中存储CFDataRef(对于CFRelease(image-> imageRef))。希望这也有助于其他人...... JR